在 Java 中将 ExecutorService 转换为守护程序

我在Java 1.6中使用了一个ExpertomoreService,只需从以下位置开始

ExecutorService pool = Executors.newFixedThreadPool(THREADS). 

当我的主线程完成时(以及线程池处理的所有任务),这个池将阻止我的程序关闭,直到我显式调用

pool.shutdown();

我是否可以避免通过以某种方式将此池使用的内部线程管理转换为 deamon 线程来调用此线程?还是我在这里错过了什么。


答案 1

可能最简单和首选的解决方案是在Marco13的答案中,所以不要被投票差异(这个答案早了几年)或接受标记所愚弄(它只是意味着这个解决方案适合OP情况,而不是一般来说它是最好的)。


您可以使用 将执行程序中的线程设置为守护程序。这将以某种方式影响执行程序服务,因为它也将成为守护程序线程,因此,如果没有其他非守护程序线程,它将停止(以及由它处理的线程)。下面是一个简单的示例:ThreadFactory

ExecutorService exec = Executors.newFixedThreadPool(4,
        new ThreadFactory() {
            public Thread newThread(Runnable r) {
                Thread t = Executors.defaultThreadFactory().newThread(r);
                t.setDaemon(true);
                return t;
            }
        });

exec.execute(YourTaskNowWillBeDaemon);

但是,如果您想获得执行器,这将使其任务完成,同时在应用程序完成时自动调用其方法,则可能需要使用Guava的MoreExecutors.getExitingExecutorService包装执行器。shutdown()

ExecutorService exec = MoreExecutors.getExitingExecutorService(
        (ThreadPoolExecutor) Executors.newFixedThreadPool(4), 
        100_000, TimeUnit.DAYS//period after which executor will be automatically closed
                             //I assume that 100_000 days is enough to simulate infinity
);
//exec.execute(YourTask);
exec.execute(() -> {
    for (int i = 0; i < 3; i++) {
        System.out.println("daemon");
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

答案 2

已经有一个内置功能可用于创建 在一段时间不活动后终止所有线程:您可以创建一个 ,向它传递所需的计时信息,然后调用此执行器服务:ExecutorServiceThreadPoolExecutorallowCoreThreadTimeout(true)

/**
 * Creates an executor service with a fixed pool size, that will time 
 * out after a certain period of inactivity.
 * 
 * @param poolSize The core- and maximum pool size
 * @param keepAliveTime The keep alive time
 * @param timeUnit The time unit
 * @return The executor service
 */
public static ExecutorService createFixedTimeoutExecutorService(
    int poolSize, long keepAliveTime, TimeUnit timeUnit)
{
    ThreadPoolExecutor e = 
        new ThreadPoolExecutor(poolSize, poolSize,
            keepAliveTime, timeUnit, new LinkedBlockingQueue<Runnable>());
    e.allowCoreThreadTimeOut(true);
    return e;
}

编辑 参考注释中的备注:请注意,当应用程序退出时,此线程池执行程序不会自动关闭。应用程序退出后,执行程序将继续运行,但不会超过 .如果根据精确的应用程序要求,必须超过几秒钟,那么Pshemo回答中的解决方案可能更合适:当线程设置为守护进程线程时,当应用程序退出时,它们将立即结束。keepAliveTimekeepAliveTime