7

我有一些执行程序服务可以安排本地任务,例如读取文件、连接到数据库等。这些进程会进行大量的日志记录,这是基于有许多线程同时运行的事实,将它们自己的东西写入日志的事实。 .

现在,在某个时间点可以引发异常,该异常会到达捕获所有异常的 main 方法。然后我将关闭所有服务并取消每个任务,希望能阻止所有进一步的消息进入日志。不幸的是,在我关闭所有内容后,这些消息仍然出现......有什么想法吗?

更新:这是一些代码

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

4 回答 4

10

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

Thread.currentThread().isInterrupted()

如果您的代码运行循环并且您希望以这种方式停止,那么这样做是一个好主意。

于 2012-11-30T10:11:27.487 回答
7

当您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
}
于 2012-11-30T10:05:43.687 回答
4

Executors 支持 2 种关闭方法

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

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

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

于 2012-11-30T09:59:52.557 回答
0

-尝试使用该shutdowNow()方法,它会关闭所有由这个 Executor throwing 启动的任务,InterruptedException不能被中断。IOSynchronized operation

例如:

ExecutorService executor = Executors.newFixedThreadPool();

executor.execute();

...
...

executor.shutdownNow();

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

于 2012-11-30T09:59:12.217 回答