[英]Non-blocking signaling between threads
I have a JavaFX app that runs two threads at startup.我有一个 JavaFX 应用程序,它在启动时运行两个线程。 One is the UI thread that must not be blocked.
一种是不得阻塞的 UI 线程。 The other is a thread that prepares a large table (it takes about 20 seconds).
另一个是准备大表的线程(大约需要20秒)。 I want to signal the UI thread when the second thread is done, so it can change the color of a rectangle from red to green.
我想在第二个线程完成时向 UI 线程发出信号,以便它可以将矩形的颜色从红色更改为绿色。 I have tried solutions using the synchronized keyword, but they all caused the UI thread to be blocked.
我尝试过使用 synchronized 关键字的解决方案,但它们都导致 UI 线程被阻塞。
I used the following resources to obtain the below code.我使用以下资源获取以下代码。
The below app simply displays a red rectangle which, after five seconds, turns to green.下面的应用程序仅显示一个红色矩形,五秒钟后变为绿色。 Explanations after the code.
代码后的解释。
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class JfxTask0 extends Application {
private Task<Void> task;
@Override
public void init() throws Exception {
task = new Task<Void>() {
@Override
protected Void call() throws Exception {
try {
Thread.sleep(5000L);
}
catch (InterruptedException xInterrupted) {
if (isCancelled()) {
System.out.println("CANCELLED!");
}
}
return null;
}
};
}
@Override
public void start(Stage primaryStage) throws Exception {
Rectangle rect = new Rectangle(25.0d, 25.0d, 50.0d, 50.0d);
rect.setFill(Color.RED);
task.stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends State> workerStateProperty,
Worker.State oldValue,
Worker.State newValue) {
if (newValue == Worker.State.SUCCEEDED) {
rect.setFill(Color.GREEN);
}
}
});
new Thread(task).start();
Group root = new Group();
ObservableList<Node> children = root.getChildren();
children.add(rect);
Scene scene = new Scene(root, 100.0D, 100.0D);
primaryStage.setScene(scene);
primaryStage.setTitle("Task");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Method init()
is declared in class javafx.application.Application
.方法
init()
在 class javafx.application.Application
中声明。 It is executed before method start()
and, as its name suggests, is used to initialize the JavaFX application.它在方法
start()
之前执行,顾名思义,它用于初始化 JavaFX 应用程序。 In this method I create the background task.在这种方法中,我创建了后台任务。 The background task merely sleeps for five seconds.
后台任务只休眠五秒钟。
In method start()
I create the red rectangle and then launch the background task but before launching the task, I register a listener with one of the task's properties.在方法
start()
中,我创建了红色矩形,然后启动了后台任务,但在启动任务之前,我用任务的一个属性注册了一个侦听器。 This property will be set to a particular value once the task completes.任务完成后,此属性将设置为特定值。
After the task is launched, I build the rest of the GUI and display it.任务启动后,我构建了GUI的rest并显示出来。
Once the task terminates, then listener is invoked and it sets the rectangle color to green.任务终止后,将调用侦听器并将矩形颜色设置为绿色。
You can use a handler for this problem.您可以使用处理程序来解决此问题。 there is example Add this in your main activity and create handler.
有示例将其添加到您的主要活动中并创建处理程序。
Handler h = new Handler(){
@Override public void handleMessage(Message msg){
switch(msg.what){
case 1:
// what you want when complete
break;
default:
break;
}
}
}
MyThread thread = new MyThread(new Messenger(h));
thread.start();
Now add this in your thread file.现在将其添加到您的线程文件中。
public class MyThread{
Messenger m;
public MyThread(Messenger m){
this.m = m;
}
public void run(){
super.run();
// your codes
//
//when your task complete
Message msg = Message.obtain();
msg.what = 1;
msg.obj = "";
try{
m.send(msg);
}catch(IOException e){
e.printStackTrace();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.