JavaFx保存停止后台任务

时间:2016-10-13 19:51:21

标签: java multithreading javafx

现在我有一个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进程)

或者有没有办法顺利杀死一个守护线程?

编辑:我的主要优先事项是后台线程不能为自己保持活力。第二个优先事项是后台线程尽可能顺利地被杀死。

1 个答案:

答案 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();
}