【问题标题】:JavaFx savely stopping Background TaskJavaFx savely 停止后台任务
【发布时间】:2016-10-13 19:51:21
【问题描述】:

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

同时我在我唯一的 Stage 中添加了一个 CloseRequestListener

stage.setOnCloseRequest( e -> running = false);

现在我的问题:

由于进程是一个守护进程,它可以在运行过程中被移除。有没有更好的方法来确保后台任务在 JavaFx 进程死亡后终止? (即使JavaFx进程被强行杀死)

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

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

【问题讨论】:

    标签: java multithreading javafx


    【解决方案1】:

    Task 已经有一个取消机制,因此无需使用running 标志自己实现此功能(您必须小心设置volatile,或使用其他方式确保对其进行更改来自一个线程在另一个线程中可见)。

    那就这样吧:

    Task<Void> task = new Task<Void>( ){
        @Override
        protected Void call() throws Exception {
            while(! isCancelled()){
                doSomething();
            }
            saveData();
            return null;
        }
    };
    

    如果您的 doSomething() 方法涉及阻塞调用,可能会抛出 InterruptedExceptions,请务必捕获异常,因为在任务上调用 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();
    }
    

    【讨论】:

    • 啊谢谢=) 不知道stop() 方法会被无异常调用吗?如果我将线程保留为守护程序,则仍然存在可以在 doSomething() 中间杀死它的问题。此外,正如您提到的那样,cancle() 调用可能会引发一个中断的异常,该异常也可能会中断 doSomething() 中途。我想尽可能地防止这种情况发生。例如,如果我更改数据,将其写入多个文件并且进程中途停止,则数据可能会变得不持久。
    • 只有在doSomething() 具有可中断的阻塞调用时才会出现问题。 stop() 将被调用,除非您使用 System.exit() 退出(这只会终止所有线程,因此除了不调用它之外没有其他方法可以解决)。
    猜你喜欢
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    • 1970-01-01
    • 2012-02-28
    相关资源
    最近更新 更多