Java 生成新线程以运行简单后台任务的替代方案?

Java 生成新线程以运行简单后台任务的替代方案?,java,javafx,Java,Javafx,我在程序的UI中有一个按钮,它调用一个需要花费很多时间才能执行的函数。(toggleLoveTrack(),在本例中) 如果我将该调用直接放在JavaFX线程上,GUI将冻结,直到执行完成 因此,另一种方法是将任务放在单独的后台线程中,执行该线程,然后在长时间执行的函数完成后使用Platform.runLater()更新UI,如下所示: loveButton.setOnAction( ( ActionEvent e ) -> { Thread taskThread = new Th

我在程序的UI中有一个按钮,它调用一个需要花费很多时间才能执行的函数。(
toggleLoveTrack()
,在本例中)

如果我将该调用直接放在JavaFX线程上,GUI将冻结,直到执行完成

因此,另一种方法是将任务放在单独的后台线程中,执行该线程,然后在长时间执行的函数完成后使用
Platform.runLater()
更新UI,如下所示:

loveButton.setOnAction( ( ActionEvent e ) -> {
    Thread taskThread = new Thread (() -> {
        audioSystem.getLastFM().toggleLoveTrack( audioSystem.getCurrentTrack() );
        Platform.runLater( () -> updateLovedIndicator() );
    });
    taskThread.setDaemon( true );
    taskThread.start();
});

有没有比每次按下按钮都生成一个新线程更好的方法呢?我认为在这种情况下,这两种方式都没有太大关系,但如果可能的话,我希望在这里做得更好

不应为每个任务生成新线程。只需创建一个,将其存储为一个字段,并将每个任务作为
runnable
提交即可

// replace this with a thread pool executor or whatever
private ExecutorService executor = Executors.newSingleThreadExecutor();
然后,在您的方法中:

executor.execute(() -> /* your code here */);

更好的是,您可以只使用
CompletableFuture.runAsync()
,而不关心执行器(任务将提交到公共fork/join池,除非您提供显式执行器)。这样,您将得到一个结果,允许您添加侦听器并进行任何进一步的处理。

为什么要将其设置为守护进程线程?如果JVM终止,我希望线程终止——它不应该使JVM保持活动状态。对于
ExecutorService
的情况,在应用程序完成时关闭它很重要(例如,从
应用程序停止
方法)或者使用创建deamon线程的
ThreadFactory
。否则JVM不会正确终止。还要注意,由于
Task
FutureTask
的子类和
Runnable
的实现,您可以将
Task
实例传递给
executor.execute()
。这意味着您在
ExecutorService
的上下文中使用时,仍然可以利用UI特定的
任务
生命周期回调(
setonSucceed
等)。