这是我的代码,有人可以解释为什么每次都起作用吗?
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);
}
}
答案 0 :(得分:3)
正如我在评论中所说,不正确的同步代码不能保证错误本身。但是,这并不意味着所说的代码在多线程上下文中使用时实际上可以工作-您只是幸运。最终,您将遇到未定义的行为,例如损坏的状态,陈旧的值和意外的异常。这是因为,如果没有同步,则不能保证一个线程执行的操作对其他任何线程都是可见的。您需要先发生先发生的关系,在java.util.concurrent
和package documentation的this SO question中有更好的描述。
与大多数UI框架/工具包一样,JavaFX是单线程的。这意味着有一个特殊的线程(在本例中为 JavaFX Application Thread )负责所有与UI相关的操作 1 。必须使用此线程(仅此线程)来访问和/或修改与“实时”场景图相关的状态(即,场景中位于显示 2 )。使用任何其他线程都可能导致上述未定义行为。
一些与UI相关的函数实际上确保在 JavaFX Application Thread 上调用它们,如果没有,通常会抛出IllegalStateException
。但是,其余的函数将使您无声地从任何线程中调用它们,但这并不意味着这样做是安全的。我相信,这样做是通过这种方式完成的,因为检查每个与UI相关的功能中的线程是维护的噩梦,并且会带来不小的影响。
1。这有点复杂。 JavaFX还具有“棱镜渲染线程”和“媒体线程”。有关更多信息,请参见Understanding JavaFX Architecture。但是请注意,从应用程序开发人员的角度来看,唯一重要的线程是 JavaFX Application Thread 。
2。 Node
对此进行了说明。请注意,某些节点(例如WebView
)在线程化方面更具限制性。这将记录在适当的位置。