在关闭我的JavaFX程序之前停止线程

时间:2013-02-15 14:47:58

标签: java javafx

我在关闭应用程序时遇到问题,因为关闭应用程序后某些线程仍在运行。 有人可以帮我一些方法来阻止所有线程在后台执行,然后杀死主线程???

[EDITED]

关于javafx的问题,我注意到许多新开发人员正面临着管理Threads的问题。我想分享一下我为简化在javafx上管理线程的生活所做的工作。我已经基于Android的AsyncTask创建了一个AsyncTask类,它基本上以简单但有效的方式执行Android的相同操作。您可以在Github project

上找到有关它的更多信息

5 个答案:

答案 0 :(得分:32)

这里有三个选项 - 最简单的方法是简单地创建你的线程作为守护,这意味着当你的主程序结束时,所有守护线程也会终止。

Thread thread = new Thread();
thread.setDaemon(true);

这是最简单的,但缺点是你不会得到一个优雅的关闭(即线程将停止,你将没有机会执行资源管理等,这可能或可能不是你的问题)。

另一种方法是保持生成的线程,当程序收到关闭信号时,迭代线程并传入某种信号以表示它们也应该终止

volatile boolean shutdown = false;

public void shutdown() {
   shutdown = true;
}

public void run() {
    while(!shutdown) { 
        ... do your work here
    }
    ... perform any cleanup work here

(注意:为了清晰起见,忽略任何异常处理)

最后一个选项是在java.util.concurrent

中使用Executor框架
ExecutorService executorService = Executors.newFixedThreadPool(10);
... assign/invoke tasks etc

... at some point later your program is told to shutdown 
... shutdown in executor too 
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS); // wait for 10s in this case
executorService.shutdownNow();

答案 1 :(得分:30)

更好的解决方法是在关闭请求上添加 EventHandler

@Override
public void start(Stage primaryStage) {
    primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
       @Override
       public void handle(WindowEvent e) {
          Platform.exit();
          System.exit(0);
       }
    });
}

答案 2 :(得分:4)

覆盖您的应用程序类

//System.exit(0) This will close all timers and threads inside the Jar application...
@Override
public void stop() throws Exception {
    super.stop(); //To change body of generated methods, choose Tools | Templates.
    System.exit(0);
}

答案 3 :(得分:2)

来自java.util.concurrent包的

Executors是可行的方法。明确地:

ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactory() {
     @Override
     public Thread newThread(Runnable runnable) {
          Thread thread = Executors.defaultThreadFactory().newThread(runnable);
          thread.setDaemon(true);
          return thread;
    }
});

具有固定ScheduledExecutorService

的Java 8版本
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, r -> {
    Thread thread = Executors.defaultThreadFactory().newThread(r);
    thread.setDaemon(true);
    return thread;
});

答案 4 :(得分:2)

Platform.exit()方法属于JavaFX上下文。 当您调用Platform.exit()时,将在上下文终止之前调用方法javafx.application.Application#stop()。 将stop()方法放入JavaFX上下文终止之前需要执行的所有操作。

使用System.exit(0)方法,应用程序突然终止。 此方法并不安全,因为如果您现在调用System.exit(0)并且Job仍在运行,可能正在数据库中执行写操作, 该应用程序将不等待作业执行,从而导致数据库损坏。

我有一个运行带有SpringBoot和线程池的JavaFX的应用程序。这就是我的处理方式。

//...
import javafx.application.Application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

@SpringBootApplication
public class Main extends Application {

    ConfigurableApplicationContext context;

    ScheduledExecutorService scheduledExecutorService;


    @Override
    public void init() {

        this.context = SpringApplication.run(getClass());

        this.context.getAutowireCapableBeanFactory().autowireBean(this);

        this.scheduledExecutorService = Executors.newScheduledThreadPool(10);

    }

    @Override
    public void stop() throws Exception {

        super.stop();

        this.context.close();

        this.scheduledExecutorService.shutdownNow();

    }


    // ...

}