在Java中将ExecutorService转换为守护进程
我正在使用Java 1.6中的ExecutoreService,简单地通过
ExecutorService pool = Executors.newFixedThreadPool(THREADS).
当我的主线程完成时(以及线程池处理的所有任务),该池将阻止我的程序closures,直到我明确地调用
pool.shutdown();
我可以避免必须通过某种方式调用此池pipe理的内部线程变成deamon线程吗? 还是我在这里错过了一些东西。
可能最简单和首选的解决scheme是在Marco13的答案,所以不要被投票差异(我的答案是几年前)或验收标记(这只是意味着我的解决scheme适合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(); } } });
已经有一个内置的function来创build一个ExecutorService
,在一段时间的不活动之后终止所有的线程:你可以创build一个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; }
编辑引用注释中的注释:请注意,此线程池执行程序不会在应用程序退出时自动closures。 执行程序将在应用程序退出后继续运行,但不会超过
keepAliveTime
。 如果根据精确的应用需求,keepAliveTime
必须超过几秒钟, Pshemo答案中的解决scheme可能会更合适:当线程设置为守护线程时,它们将在应用程序时立即结束退出。
我会使用Guava的ThreadFactoryBuilder类。
ExecutorService threadPool = Executors.newFixedThreadPool(THREADS, new ThreadFactoryBuilder().setDaemon(true).build());
如果你还没有使用番石榴,我会使用一个ThreadFactory子类,如Pshemo的答案顶部所述
是。
你只需要创build你自己的ThreadFactory
类来创build守护线程而不是普通的线程。
如果你有一个已知的任务列表,你完全不需要守护线程。 提交所有任务后,您可以简单地在ExecutorService上调用shutdown()。
当你的主线程完成后,使用awaitTermination()方法为提交的任务提供完成时间。当前提交的任务将被执行,一旦线程池完成,线程池将终止它的控制线程。
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); }