如何在不丢失任务的情况下关闭和实例化 Executorservice
How to shutdown and reinstantiate an Executor Service without loosing tasks
我不完全明白,我应该如何在偶尔有即将到来的任务的应用程序中实现 ExecutorService。每个任务运行大约 15 分钟(有时更长)。有时一天有 10 个任务,有时整个星期 none。
因此,如果队列中没有剩余任务,则在执行一些任务后,我想关闭执行程序,因为它不再需要,以便垃圾收集器可以完成它的工作。
调用 shutdown 后,没有新任务排队到执行器。
现在,我的问题是我必须确保所有任务都已完成。这意味着,在调用 shutdown 之后,我必须确保在提交新任务之前实例化了一个新的 Executor Service。我必须等到旧的执行器服务关闭(或终止?)并启动一个新的。我应该如何实施?
这是我的方法:
// sync block to check for each task if a new Executor Service has to be created before submitting the task
synchronized (this) {
// do I have to check both isSutdown and isTerminated?
if (null == businessTaskExecutor || businessTaskExecutor.isShutdown() || businessTaskExecutor.isTerminated()) {
// simply init a new one
businessTaskExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
} else if (businessTaskExecutor.isTerminating()) {
// the termination process has started and is not done.
// Do I have to wait for the old executor or can I simply init a new one without waiting?
while (!businessTaskExecutor.isTerminated()) { }
businessTaskExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
}
}
Future<?> future = businessTaskExecutor.submit(() -> new BusinessTaskRunnable(businessTask));
if (future.isDone() && businessTaskExecutor.getQueue().isEmpty()) {
businessTaskExecutor.shutdown();
try {
if (!businessTaskExecutor.awaitTermination(1, TimeUnit.HOURS)) {
businessTaskExecutor.shutdownNow();
}
} catch (InterruptedException ex) {
businessTaskExecutor.shutdownNow();
Thread.currentThread().interrupt();
}
}
解释:
如果执行者是null/shutdown/terminated,我会初始化一个新的,到目前为止一切顺利。
否则,如果执行程序当前正在终止(因为调用了关闭),则执行程序将不会接受进一步的任务。所以我等到它终止,然后启动一个新的。
之后我提交我的任务......
如果队列中没有其他任务,我只会关闭执行程序。尽管我等了一个小时,因为仍然可能有 运行 任务。
是否有更好的实现我希望的行为?
附加信息:我使用 ThreadPoolExecutor,因为我需要 getQueue() 检查它是否为空。我还可以在不同的实现中使用任何其他类型的执行器服务。
提前致谢。
I want to shutdown the executor as it is not needed anymore and so
that the garbage collector can to its job.
但是 需要它,这就是您要重新创建它的原因。无论执行程序是否关闭,GC 都可以完成它的工作(除非你设法创建了一些非常特殊的东西,例如 ThreadLocal
会以某种方式将对象绑定到执行程序)。
I read that the garbage collector will only be invoked if I shut the
executor down.
你要么记错了,要么阅读了错误的信息。
由于您是 运行 单线程,因此您实际上什至不需要担心池配置。一个长寿的Executors.newFixedThreadPool(1);
就是你所需要的。
如果您确实需要释放资源,您可以使用类似 new ThreadPoolExecutor(0, 1, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<BusinessTaskRunnable>());
的配置 core pool size。但这是无关紧要的微优化,一个线程不应该有所作为。
我不完全明白,我应该如何在偶尔有即将到来的任务的应用程序中实现 ExecutorService。每个任务运行大约 15 分钟(有时更长)。有时一天有 10 个任务,有时整个星期 none。
因此,如果队列中没有剩余任务,则在执行一些任务后,我想关闭执行程序,因为它不再需要,以便垃圾收集器可以完成它的工作。 调用 shutdown 后,没有新任务排队到执行器。
现在,我的问题是我必须确保所有任务都已完成。这意味着,在调用 shutdown 之后,我必须确保在提交新任务之前实例化了一个新的 Executor Service。我必须等到旧的执行器服务关闭(或终止?)并启动一个新的。我应该如何实施?
这是我的方法:
// sync block to check for each task if a new Executor Service has to be created before submitting the task
synchronized (this) {
// do I have to check both isSutdown and isTerminated?
if (null == businessTaskExecutor || businessTaskExecutor.isShutdown() || businessTaskExecutor.isTerminated()) {
// simply init a new one
businessTaskExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
} else if (businessTaskExecutor.isTerminating()) {
// the termination process has started and is not done.
// Do I have to wait for the old executor or can I simply init a new one without waiting?
while (!businessTaskExecutor.isTerminated()) { }
businessTaskExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
}
}
Future<?> future = businessTaskExecutor.submit(() -> new BusinessTaskRunnable(businessTask));
if (future.isDone() && businessTaskExecutor.getQueue().isEmpty()) {
businessTaskExecutor.shutdown();
try {
if (!businessTaskExecutor.awaitTermination(1, TimeUnit.HOURS)) {
businessTaskExecutor.shutdownNow();
}
} catch (InterruptedException ex) {
businessTaskExecutor.shutdownNow();
Thread.currentThread().interrupt();
}
}
解释:
如果执行者是null/shutdown/terminated,我会初始化一个新的,到目前为止一切顺利。 否则,如果执行程序当前正在终止(因为调用了关闭),则执行程序将不会接受进一步的任务。所以我等到它终止,然后启动一个新的。 之后我提交我的任务...... 如果队列中没有其他任务,我只会关闭执行程序。尽管我等了一个小时,因为仍然可能有 运行 任务。
是否有更好的实现我希望的行为?
附加信息:我使用 ThreadPoolExecutor,因为我需要 getQueue() 检查它是否为空。我还可以在不同的实现中使用任何其他类型的执行器服务。
提前致谢。
I want to shutdown the executor as it is not needed anymore and so that the garbage collector can to its job.
但是 需要它,这就是您要重新创建它的原因。无论执行程序是否关闭,GC 都可以完成它的工作(除非你设法创建了一些非常特殊的东西,例如 ThreadLocal
会以某种方式将对象绑定到执行程序)。
I read that the garbage collector will only be invoked if I shut the executor down.
你要么记错了,要么阅读了错误的信息。
由于您是 运行 单线程,因此您实际上什至不需要担心池配置。一个长寿的Executors.newFixedThreadPool(1);
就是你所需要的。
如果您确实需要释放资源,您可以使用类似 new ThreadPoolExecutor(0, 1, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<BusinessTaskRunnable>());
的配置 core pool size。但这是无关紧要的微优化,一个线程不应该有所作为。