JavaFX 多线程
JavaFX Multithreading
我的 JavaFx 应用程序遇到了一个问题。
前言:我不想只针对我的应用程序,而是想概括一下,以便像我这样的人对类似情况有所了解。
背景:使用fxml文件和多线程概念实现Javafx应用程序。
总结:我尝试制作一个基本上使用多线程来完成一些任务的应用程序,一旦多线程完成,它将依次移动到另一个任务。在执行多线程时,主 GUI 冻结。
我做了什么,
//This is Main class
Parent Root -> defined on top
public Parent createContent(){
try{
root = FXMLLoader.load(getClass().getResource("Layout.fxml"));
}catch { .....}
}
public void start(){
stage.setScene(new Scene(createContent()));
Task<Void> task = new Task<Void>() {
@Override
public Void call() throws Exception {
Thread.sleep(1000);
return null ;
}
};
task.setOnSucceeded(event->{
stage.show();
});
new Thread(task).run();
}
public static void main(String[] args) {
launch(args);
}
// This is inside the controller on button click event
@FXML
private void start(ActionEvent event) { <---- This one is button click event
Thread t1 = new Thread(new Mul());
t1.start();
Thread t2 = new Thread (new Mul());
t2.start();
}
// Finally
public class Mul implements Runnable {
public void type() {
for (int a = 0; a < 200000; a++) {
System.out.println( Thread.currentThread().getName()+ " says " + a);
}
}
@Override
public void run() {
type();
}
}
现在,这是结果。
如果我只是从控制器启动线程,那么当线程在后台 运行 时,我的主应用程序不会冻结。但是,由于应用程序按顺序运行,即下一步仅在线程完成工作时才起作用
我可以使用 t1.join() 和 t2.join() ,但是这样做会冻结我的主应用程序(这里的主应用程序是主 GUI)并且我无法继续它直到线程完成。
最佳解决方案是什么,这样我就可以在不阻塞主应用程序的情况下使用多线程,或者我在这里做错了什么? (info,我通过遵循 Stack overflow 和 google 的不同建议得出了这个解决方案)
为什么不做
Task<Void> task = new Task<Void>() {
@Override
public Void call() {
Mul m1 = new Mul();
m1.run();
Mul m2 = new Mul();
m2.run();
return null ;
}
};
new Thread(task).start();
如果你真的想要 "chain" 不同的任务,从另一个的 onSucceeded
处理程序中调用一个:
Task<Void> task1 = new Task<Void>() {
@Override
public Void call() {
new Mul().run();
return null ;
}
};
Task <Void> task2 = new Task<Void>() {
@Override
public Void call() {
new Mul().run();
return null ;
}
};
task1.setOnSucceeded(e -> new Thread(task2).start());
new Thread(task1).start();
显然,如果您将 Mul
设为 Task
子类而不是 Runnable
,这会更清晰,并且最好将 Executor
与守护线程等一起使用,但这应该会给你灵感。
我的 JavaFx 应用程序遇到了一个问题。
前言:我不想只针对我的应用程序,而是想概括一下,以便像我这样的人对类似情况有所了解。
背景:使用fxml文件和多线程概念实现Javafx应用程序。
总结:我尝试制作一个基本上使用多线程来完成一些任务的应用程序,一旦多线程完成,它将依次移动到另一个任务。在执行多线程时,主 GUI 冻结。
我做了什么,
//This is Main class
Parent Root -> defined on top
public Parent createContent(){
try{
root = FXMLLoader.load(getClass().getResource("Layout.fxml"));
}catch { .....}
}
public void start(){
stage.setScene(new Scene(createContent()));
Task<Void> task = new Task<Void>() {
@Override
public Void call() throws Exception {
Thread.sleep(1000);
return null ;
}
};
task.setOnSucceeded(event->{
stage.show();
});
new Thread(task).run();
}
public static void main(String[] args) {
launch(args);
}
// This is inside the controller on button click event
@FXML
private void start(ActionEvent event) { <---- This one is button click event
Thread t1 = new Thread(new Mul());
t1.start();
Thread t2 = new Thread (new Mul());
t2.start();
}
// Finally
public class Mul implements Runnable {
public void type() {
for (int a = 0; a < 200000; a++) {
System.out.println( Thread.currentThread().getName()+ " says " + a);
}
}
@Override
public void run() {
type();
}
}
现在,这是结果。 如果我只是从控制器启动线程,那么当线程在后台 运行 时,我的主应用程序不会冻结。但是,由于应用程序按顺序运行,即下一步仅在线程完成工作时才起作用
我可以使用 t1.join() 和 t2.join() ,但是这样做会冻结我的主应用程序(这里的主应用程序是主 GUI)并且我无法继续它直到线程完成。
最佳解决方案是什么,这样我就可以在不阻塞主应用程序的情况下使用多线程,或者我在这里做错了什么? (info,我通过遵循 Stack overflow 和 google 的不同建议得出了这个解决方案)
为什么不做
Task<Void> task = new Task<Void>() {
@Override
public Void call() {
Mul m1 = new Mul();
m1.run();
Mul m2 = new Mul();
m2.run();
return null ;
}
};
new Thread(task).start();
如果你真的想要 "chain" 不同的任务,从另一个的 onSucceeded
处理程序中调用一个:
Task<Void> task1 = new Task<Void>() {
@Override
public Void call() {
new Mul().run();
return null ;
}
};
Task <Void> task2 = new Task<Void>() {
@Override
public Void call() {
new Mul().run();
return null ;
}
};
task1.setOnSucceeded(e -> new Thread(task2).start());
new Thread(task1).start();
显然,如果您将 Mul
设为 Task
子类而不是 Runnable
,这会更清晰,并且最好将 Executor
与守护线程等一起使用,但这应该会给你灵感。