【问题标题】:Threads in JavaFX: do threads need to be killed?JavaFX 中的线程:是否需要杀死线程?
【发布时间】:2017-09-29 18:27:56
【问题描述】:

我正在使用 JavaFX 编写应用程序,我的理解是,虽然 UI 在线程中运行,但所有其他非 UI 操作必须在另一个线程中运行。到目前为止,我发现的所有示例都是以下内容的变体:

myButton.setOnAction(new EventHandler<ActionEvent>(){
    @Override
    public void handle(ActionEvent a) {

        // Some UI operations

        new Thread() {
            public void run() {

                // Some non-UI operations

                Platform.runLater(new Runnable() {
                    public void run() {

                        // Some operations to update the UI
                    }
                });
            }
        }.start();
    }
});

我的问题是:您是否需要以某种方式杀死线程以释放其资源?在示例中,我似乎从来没有人使用 Thread.join 或任何其他类似方法。

另外,这样使用 setDaemon 是否可取?

myButton.setOnAction(new EventHandler<ActionEvent>(){
    @Override
    public void handle(ActionEvent a) {

        // Some UI operations

        final Thread child = new Thread() {
            public void run() {

                // Some non-UI operations

                Platform.runLater(new Runnable() {
                    public void run() {

                        // Some operations to update the UI
                    }
                });
            }
        };

        child.setDaemon(true);
        child.start();

    }
});

注意: 根据这个线程 (JavaFX multithreading - joining threads won't update the UI) Thread.join 不能使用,但它似乎没有解决不再需要的线程会发生什么或如何杀死它们的问题。

【问题讨论】:

  • 这取决于你在做什么。请详细描述一下您在这些线程上实际尝试执行的操作。
  • 我想简短的回答是:“这很复杂”。很难为所有可能性提供一个明确的包罗万象的答案。在确定适当的线程管理策略时需要考虑很多因素。例如,线程中的代码是否需要像原子事务一样运行才能在关闭时不让内容处于不一致的状态?线程是否在应用程序的整个长度内运行(所以在启动时开始并在关闭时结束)?编写的线程代码是否可以正确响应中断?是否需要基于用户的取消?线程在池中吗?使用执行器?
  • 其实没那么复杂。本质上,应用程序通过文本框从用户那里获取一些输入,对其进行处理并将其发送到服务器(即非 UI 部分)。然后,服务器响应在到达时显示在用户界面的 TextArea 上(即 Platform.runLater 部分)。那么问题来了,非UI线程如何处理呢?是显式杀死还是 Java 自动释放资源?

标签: java multithreading javafx


【解决方案1】:

当没有为它们安排任何事情时,线程将老化。但是,依赖它并不是一个好习惯,因为它会占用资源。

更好的方法是使用ExecutorService,如the documentation 中所述。 ThreadPoolExecutor 可以运行一个或多个线程。您可以使用相同的执行器来继续提交可运行的任务,它们将在它管理的线程上执行。该文档提供了有关如何在应用程序结束时关闭执行程序服务的示例。如果您确信没有未完成的任务正在执行,您可以发出shutdownNow() 以立即清理所有线程。

【讨论】:

  • "如果没有为它们安排任何事情,线程将会老化。"
  • 抱歉术语不准确。在您的示例中,您创建了一个Thread 对象,由变量child 引用。您提交的Runnable 在计划时包含对它的引用。当child 变量超出范围,并且runnable 本身完成时,Thread 对象将被垃圾回收。这最终会发生,并且无法保证何时发生。因此,我使用松散的术语“老化”。
  • 感谢您的回复。我也考虑了 ExecutorService 选项,但我最终选择了 setDaemon 方法(第二个示例),因为它需要对我已有的内容进行较少的更改(第一个示例)。也就是说,setDaemon 方法会运作良好吗?
  • setDaemon 几乎独立于使用执行器服务。如果需要,您可以使用执行程序服务并将其配置为使用守护线程,或者仅使用非守护线程(默认情况下)。同样,您可以手动创建线程(不使用执行器服务)并使其成为守护线程。
猜你喜欢
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
  • 1970-01-01
  • 2011-04-19
  • 1970-01-01
  • 2015-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多