By Mishax


2019-04-12 10:31:14 8 Comments

Here is my code, can someone explain why it works every time?

package dingding;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;


public class Dingding extends Application {

    TextField tfAuto = new TextField("0");
    AutoRunThread runner = new AutoRunThread();
    boolean shouldStop = false;

    private class AutoRunThread extends Thread {

        @Override
        public void run() {
            while (true) {
                int i = Integer.parseInt(tfAuto.getText());
                ++i;
                tfAuto.setText(String.valueOf(i));
                try {
                Thread.sleep(1000);
                } catch (Throwable t) {

                }
                if (shouldStop) {
                    runner = null;
                    shouldStop = false;
                    return;
                }
            }
        }
    }

    @Override
    public void start(Stage primaryStage) {

        Button btnStart = new Button("Increment Automatically");
        Button btnStop = new Button("Stop Autotask");

        btnStart.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if (runner == null) {
                    runner = new AutoRunThread();
                    runner.setDaemon(true);
                }
                if (runner != null && !(runner.isAlive())) {
                    runner.start();
                }
            }
        });

        btnStop.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                shouldStop = true;
            }
        });


        VBox rootBox = new VBox();
        HBox autoBox = new HBox();

        autoBox.getChildren().addAll(tfAuto, btnStart, btnStop);

        rootBox.getChildren().addAll(autoBox);

        Scene scene = new Scene(rootBox, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

1 comments

@Slaw 2019-04-15 11:05:10

As I said in my comment, improperly synchronized code doesn't guarantee errors per se. However, that doesn't mean said code, when used in a multi-threaded context, is actually working—you're merely getting lucky. Eventually you'll run into undefined behavior such as corrupted state, stale values, and unexpected exceptions. This is because, without synchronization, actions performed by one thread are not guaranteed to be visible to any other thread. You need a happens-before relationship, better described in the package documentation of java.util.concurrent and this SO question.

JavaFX, like most UI frameworks/toolkits, is single threaded. This means there's a special thread—in this case, the JavaFX Application Thread— that is responsible for all UI related actions1. It is this thread, and this thread only, that must be used to access and/or modify state related to a "live" scene graph (i.e. nodes that are in a scene that's in a window that's showing2). Using any other thread can lead to the undefined behavior described above.

Some UI related functions actually ensure they're being called on the JavaFX Application Thread, usually throwing an IllegalStateException if not. However, the remaining functions will silently let you call them from any thread—but that doesn't mean it's safe to do so. This is done this way, I believe, because checking the thread in every UI related function is a maintenance nightmare and would incur a not-insignificant performance cost.


1. It's slightly more complicated that this; JavaFX also has a "prism render thread" and a "media thread". See Understanding JavaFX Architecture for more information. But note that, from an application developer's point of view, the only thread that matters is the JavaFX Application Thread.

2. This is documented by Node. Note that some nodes, such as WebView, are more restrictive when it comes to threading; this will be documented in the appropriate places.

Related Questions

Sponsored Content

0 Answered Questions

JavaFX loading system icons in a background thread

  • 2018-10-06 08:13:42
  • fluxi
  • 47 View
  • 0 Score
  • 0 Answer
  • Tags:   java javafx

1 Answered Questions

[SOLVED] Run Service in background Thread

1 Answered Questions

[SOLVED] JavaFX background thread task should play music in a loop as background thread

  • 2015-08-03 10:10:45
  • user3747849
  • 2747 View
  • 4 Score
  • 1 Answer
  • Tags:   audio javafx

1 Answered Questions

[SOLVED] Trouble with JavaFX background threads

0 Answered Questions

JavaFX - method returning before background thread completes

1 Answered Questions

[SOLVED] Focus Traversable on CustomMenuItem. Content loose focus on mouse hover

  • 2016-04-06 19:08:41
  • user43968
  • 152 View
  • 0 Score
  • 1 Answer
  • Tags:   java javafx focus

0 Answered Questions

Custom TreeCell with cell factory, and background threads

  • 2016-02-15 19:44:24
  • Sonicsmooth
  • 409 View
  • 0 Score
  • 0 Answer
  • Tags:   javafx

1 Answered Questions

Transmit Strings to Main thread from Background thread

1 Answered Questions

[SOLVED] javafx background thread issue ?

2 Answered Questions

[SOLVED] JavaFX - Background Thread for SQL Query

  • 2013-02-14 15:55:24
  • Uniqum
  • 10044 View
  • 11 Score
  • 2 Answer
  • Tags:   javafx-2 javafx

Sponsored Content