谈到一个ExecutorService在Java守护进程(Turning an ExecutorSe

2019-07-05 08:05发布

我在Java中使用1.6 ExecutoreService,开始简单地通过

ExecutorService pool = Executors.newFixedThreadPool(THREADS). 

当我的主线程完成(由线程池处理的所有任务一起),该池会阻止我的程序从关闭,直到我明确要求

pool.shutdown();

我能避免被莫名其妙地转动内螺纹使用该池管理成守护进程线程调用这个? 还是我失去了一些东西在这里。

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

但是,如果你想要得到执行,这将让自己的任务完成,并在同一时间将自动调用其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();
        }
    }
});


Answer 2:

目前已经是创建一个内置功能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必须是超过几秒钟,在该解决方案通过Pshemo答案可能更合适:当线程设置为守护线程,那么他们将立即结束时,应用程序退出。



Answer 3:

我会用番石榴的ThreadFactoryBuilder类。

ExecutorService threadPool = Executors.newFixedThreadPool(THREADS, new ThreadFactoryBuilder().setDaemon(true).build());

如果你还没有使用番石榴,我用的ThreadFactory子类去喜欢在开头部分介绍Pshemo的答案



Answer 4:

是。

你只需要创建自己ThreadFactory创建守护线程,而不是普通的线程类。



Answer 5:

如果你只是想在一个地方使用它,那么你可以内联java.util.concurrent.ThreadFactory实施,比如被用于4个线程,你会写(例如显示为拉姆达假设的Java 1.8或更新版本)池:

ExecutorService pool = Executors.newFixedThreadPool(4,
        (Runnable r) -> {
            Thread t = new Thread(r);
            t.setDaemon(true);
            return t;
        }
);

但我通常希望我所有的线程工厂,生产守护线程,所以我添加了一个实用工具类,如下所示:

import java.util.concurrent.ThreadFactory;

public class DaemonThreadFactory implements ThreadFactory {

    public final static ThreadFactory instance = 
                    new DaemonThreadFactory();

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
}

这让我很容易地通过DaemonThreadFactory.instanceExecutorService ,如

ExecutorService pool = Executors.newFixedThreadPool(
    4, DaemonThreadFactory.instance
);

或者用它来轻松地从一个启动一个守护线程Runnable ,如

DaemonThreadFactory.instance.newThread(
    () -> { doSomething(); }
).start();


Answer 6:

该解决方案是类似于@ Marco13的但不是创造我们自己ThreadPoolExecutor ,我们可以修改返回的一个Executors#newFixedThreadPool(int nThreads) 这是如何做:

ExecutorService ex = Executors.newFixedThreadPool(nThreads);
 if(ex instanceof ThreadPoolExecutor){
    ThreadPoolExecutor tp = (ThreadPoolExecutor) ex;
    tp.setKeepAliveTime(time, timeUnit);
    tp.allowCoreThreadTimeOut(true);
}


Answer 7:

如果你有任务的已知列表,你不都需要守护线程。 您可以在提交给所有的任务后,只需调用的ExecutorService的shutdown()方法。

当你的主线程完成后,使用awaitTermination()方法,以便有时间提交任务complete.The目前提交的任务将被执行,而一旦他们已经结束线程池将终止其控制线程。

for (Runnable task : tasks) {
  threadPool.submit(task);
}
threadPool.shutdown();
/*... do other stuff ...*/
//All done, ready to exit
while (!threadPool.isTerminated()) {
  //this can throw InterruptedException, you'll need to decide how to deal with that.
  threadPool.awaitTermination(1,TimeUnit.SECOND); 
}


文章来源: Turning an ExecutorService to daemon in Java