import java.util.concurrent.atomic.AtomicBoolean; import javafx.application.Application; import javafx.application.Platform; import javafx.beans.property.SimpleIntegerProperty; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.Tooltip; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class MTCssFail extends Application { @Override public void start(Stage stage) { stage.setTitle("Concurrent CSS StyleManager test"); final VBox root = new VBox(5); root.setPadding(new Insets(5)); Scene scene = new Scene(root, 600, 450); final AtomicBoolean err = new AtomicBoolean(false); final Label statusLabel = new Label("IDLE"); final SimpleIntegerProperty count = new SimpleIntegerProperty(0); final Label countLabel = new Label(); countLabel.textProperty().bind(count.asString()); Button button = new Button("Start Threads"); button.setOnAction(e -> { statusLabel.setText("RUNNING..."); Thread[] bgThreads = new Thread[10]; count.set(bgThreads.length); err.set(false); for (int i = 0; i < bgThreads.length; i++) { Thread thr = new Thread(() -> { try { for (int j = 0; j < 1000; j++) { Tooltip tip = new Tooltip("Tooltip #" + j); } } catch (RuntimeException ex) { err.set(true); } finally { Platform.runLater(() -> { synchronized (count) { int c = count.get() - 1; count.set(c); } }); } }); thr.setName("My Thread - " + i); thr.setDaemon(true); bgThreads[i] = thr; } for (Thread thr : bgThreads) { thr.start(); } Thread bgMonitorThr = new Thread(() -> { try { for (Thread thr : bgThreads) { thr.join(); } } catch (InterruptedException ex) { System.err.println(ex); } Platform.runLater(() -> statusLabel.setText(err.get() ? "FAIL" : "DONE")); }); bgMonitorThr.setName("Monitor Thread"); bgMonitorThr.setDaemon(true); bgMonitorThr.start(); }); root.getChildren().addAll(countLabel, statusLabel, button); stage.setScene(scene); stage.show(); } public static void main(String[] args) { Application.launch(args); } }