现在我有一个JavaFx程序,在线程中使用JavaFx任务作为后台进程。
Task<Void> task = new Task<Void>( ){
@Override
protected Void call() throws Exception {
while(running){
doSomething();
}
saveData();
return null;
}
};
Thread th = new Thread(task);
th.start();
我想尽可能顺利地停止这个过程(意思是我想通过设置running = false来停止这个过程;因此尽可能调用save()方法。同时我想确保在JavaFx进程(窗口)关闭后,后台进程没有机会继续运行。
目前我正在将Thread设置为Deamon,以确保在JavaFx进程停止后进程终止(两个进程是唯一正在运行的进程)
th.setDeamon(true);
同时我将CloseRequestListener添加到我唯一的Stage
stage.setOnCloseRequest( e -> running = false);
现在我的问题:
由于该过程是Deamon,因此可以在运行过程中将其删除。有没有更好的方法来确保后台任务在JavaFx进程死亡后死亡? (即使强行杀死JavaFx进程)
或者有没有办法顺利杀死一个守护线程?
编辑:我的主要优先事项是后台线程不能为自己保持活力。第二个优先事项是后台线程尽可能顺利地被杀死。
答案 0 :(得分:4)
Task
已经有了取消机制,因此无需自行使用running
标记(您必须谨慎制作volatile
)或使用其他方式确保从一个线程对它的更改在另一个线程中可见。
所以就这样做:
Task<Void> task = new Task<Void>( ){
@Override
protected Void call() throws Exception {
while(! isCancelled()){
doSomething();
}
saveData();
return null;
}
};
如果你的doSomething()
方法涉及阻止可能抛出InterruptedException
的调用,请务必捕获异常,因为在任务上调用cancel()
会中断其线程:
Task<Void> task = new Task<Void>( ){
@Override
protected Void call() throws Exception {
while(! isCancelled()){
try {
doSomething();
} catch (InterruptedException exc) {
if (isCancelled()) {
break ;
}
}
}
saveData();
return null;
}
};
最后,您不应该依赖舞台上的setOnCloseRequest()
:仅在有外部调用关闭窗口时调用此方法(例如,用户按下本机窗口关闭按钮)。例如,如果您致电Platform.exit()
,它将无法执行。而是覆盖Application.stop()
方法:
@Override
public void stop() {
task.cancel();
}