Java - 停止 ExecutorService 中的所有任务

9
我有几个执行器服务,它们会调度本地任务,例如读取文件、连接数据库等。这些进程会进行大量日志记录,由于有许多线程同时运行并写入自己的日志,因此日志非常繁琐。
现在,在某个时间点上,可能会引发异常,该异常会到达捕获所有异常的主方法。然后,我将关闭所有服务并取消每个任务,希望防止所有进一步的消息出现在日志中。不幸的是,关闭所有服务后仍然会显示消息... 有什么想法吗?
更新: 以下是一些代码。
public class Scheduler{

private final ExecutorService service;
private final ConcurrentMap<Object, Future<V>> cache;

...

public void shutDown() {
    service.shutdownNow();
    for (Future task : cache.values())
        task.cancel(true);
}

如果您不介意的话,请给我们一些代码。记录日志是否以异步方式完成?您是否使用了shutdown而不是shutdownNow?有无数个原因。 - user381105
2
你关闭服务并取消任务并不意味着那些任务会立即停止。 - assylias
4个回答

10

这项任务将继续运行,直到它检测到线程已被中断。当调用某些系统或线程函数时,可能会抛出异常。在您的情况下,您可能需要通过调用

Thread.currentThread().isInterrupted()

来自行检查。如果您的代码运行循环并且希望以此方式停止,则执行此操作是个好主意。


9
当你调用shutdownNow关闭执行器或调用cancel(true)(顺便说一下,shutdownNow已经取消了已经提交的任务,因此你的循环是不必要的),你的任务会被中断。
根据它们对中断的反应方式,它们可能会:
  • 立即停止正在进行的工作
  • 在一段时间后停止正在进行的工作,因为中断信号没有被定期检查
  • 继续进行它们正在做的事情,因为中断信号已被忽略
例如,如果你的任务运行一个while(true)循环,可以将其替换为类似以下内容的代码:
while(!Thread.currentThread().isInterrupted()) {
    //your code here
}
cleanup();
//and exit

另一个例子:
for (int i = 0; i < aBigNumber; i++) {
    if (Thread.currentThread().isInterrupted()) { break; }
    //rest of the code for the loop
}
cleanup();
//and exit

举个例子,如果你调用一个抛出InterruptedException的方法:

try {
    Thread.sleep(forever); //or some blocking IO or file reading...
} catch (InterruptedException e) {
    cleanup();
    Thread.currentThread.interrupt();
    //and exit
}

@Bober02 在你的任务中,你需要定期检查线程是否被中断 - 当你检测到中断时,如果有必要就清理并退出任务。 - assylias
说实话,我不太明白这个。我正在向执行器服务提交一个任务,该服务在内部存储所有线程。我能做的就是使用API来关闭它。我应该监视哪些线程? - Bober02
1
@Bober02 我已经添加了一些你的可运行任务(Runnables)可能看起来像什么的例子 - 希望现在更清楚了。 - assylias

5

执行器支持2种关机方式

shutdown() : 启动有序关闭,先前提交的任务将被执行,但不会接受新任务。如果已经关闭,则调用没有额外的效果。

shutdownNow() : 尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表。 除了尽最大努力停止正在执行的任务之外,没有其他保证。

Ref : http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()


7
不完全正确 - shutdownNow 方法并没有“强制”关闭任务,它只是中断了它们,这可能会停止它们也可能不会停止。 - assylias
1
同意@assylias。会编辑我的帖子以纳入您的评论。谢谢。 - rai.skumar
有没有强制关闭任务的方法? - Jay Thakkar
为什么你想要强制关闭?这不是一个好主意,这也是Java没有提供任何直接方法的原因。(stop/suspend已被弃用) - rai.skumar
到目前为止,这是我找到的最好的答案。现在按预期工作。再次感谢。 - Peter Perháč

0

- 尝试使用shutdowNow()方法,它将关闭此执行器启动的所有任务,并抛出InterruptedException,但IO同步操作无法中断。

例如:

ExecutorService executor = Executors.newFixedThreadPool();

executor.execute();

...
...

executor.shutdownNow();

- cancel(true) 方法可以与 submit() 方法一起使用,关闭特定任务。


这是不正确的 - shutdownNow 不会关闭任务,它会中断它们,可能会或可能不会将它们关闭。 - assylias

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接