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

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (26)

我在Java 1.6中使用了一个ExecutoreService,简单地通过

ExecutorService pool = Executors.newFixedThreadPool(THREADS). 

当我的主线程完成时(以及线程池处理的所有任务),该池将阻止我的程序关闭,直到我明确地调用

pool.shutdown();

我可以避免必须通过某种方式调用这个池来使用这个池的内部线程变成deamon线程吗?或者我在这里错过了一些东西。

提问于
用户回答回答于

不要被投票差异或验收标记(这意味着我的解决方案适用于OP情况下并不是最好)欺骗。

您可以使用ThreadFactory将Executor中的线程设置为守护进程。这将影响执行程序服务的方式,它也会变成守护程序线程,因此如果不存在其他非守护程序线程,它将停止(并由它处理线程)。这是一个简单的例子:

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);

但是如果你想获得执行者来完成它的任务,同时在shutdown()应用程序完成时自动调用它的方法,你可能想要用你的执行者包装 MoreExecutors.getExitingExecutorService

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();
        }
    }
});
用户回答回答于

已经有一种内置的功能来创建一个ExecutorService在一段时间不活动后终止所有线程:您可以创建一个ThreadPoolExecutor,传递所需的时间信息,然后调用allowCoreThreadTimeout(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;
}

引用注释中的注释:请注意,该线程池执行器在应用程序退出时不会自动关闭。执行程序将在应用程序退出后继续运行,但不会超过keepAliveTime。如果根据精确的应用程序需求,它keepAliveTime必须超过几秒钟,解决方案可能更合适:当线程设置为守护线程时,它们将在应用程序退出时立即结束。

扫码关注云+社区