我正在使用Executors进行线程池,并提交任务。 executorService.shutdownNow是否会关闭所有任务,即使其中一些任务可能在对数据库或Socket的I / O调用时被阻止?
答案 0 :(得分:4)
这取决于你的任务是否写得很好!
documentation说:“shutdown()方法将允许先前提交的任务在终止之前执行,而shutdownNow()方法则阻止等待任务启动并尝试停止当前正在执行的任务。”
然而,Java并没有“凭空”杀死线程。它试图中断它们。当shtudownNow尝试中断它们时,一个好的任务会抛出某种InterruptException
,然后优雅地结束。你提到套接字通信 - 大多数体面的客户端阻塞方法如果被中断就会抛出一个中断的异常。
错误任务的一个例子可能(显然)运行while(true) { readChunk(); if(endOfChunks) { break;} }
的线程。这不提供优雅的中断检查!这是一个旧规则,不使用while循环等待,而是wait()
使用syncronized
对可能被中断的'blocker'对象。
答案 1 :(得分:1)
不,没有保证。如果您看到ExecutorService#shutdownNow的API文档。它说,
除了尽力尝试停止处理主动执行任务之外,没有任何保证。
如果您希望阻止,直到所有任务在关机请求后完成执行,请使用ExecutorService#awaitTermination。
答案 2 :(得分:1)
当无法处理中断(java.io)时,需要非标准的关闭逻辑。
我解决这个问题的解决方案结合了'Java Concurrency In Practice'中的示例'TrackingExecutorService'和'SocketUsingTask'。
public interface Shutdownable {
public void shutdown();
}
public class ShutdowningExecutor extends ThreadPoolExecutor{
private final Set runningShutdownables
= Collections.synchronizedSet(new HashSet());
@Override
protected RunnableFuture newTaskFor(final Callable callable){
if (callable instanceof Shutdownable) {
runningShutdownables.add((Shutdownable) callable);
return super.newTaskFor(new Callable(){
@Override
public T call() throws Exception {
T t = callable.call();
runningShutdownables.remove((Shutdownable) callable);
return t;
}
});
} else
return super.newTaskFor(callable);
}
public void shutdownAll() {
for(Shutdownable shutdownable : runningShutdownables) {
shutdownable.shutdown();
}
}
@Override
public List shutdownNow(){
shutdownAll();
return super.shutdownNow();
}
}
public abstract class ShutdownableViaCloseable implements Shutdownable{
private Closeable closeable;
protected synchronized void setCloseable(Closeable c) { closeable = c; }
public synchronized void shutdown() {
try {
if (closeable != null)
closeable.close();
} catch (IOException ignored) { }
}
}
public class MySocketTask extends ShutdownableViaCloseable implements Callable {
public MySocketTask(Socket s) {
setCloseable(s);
//constructor stuff
}
public Void call() {
try (Socket socket = this.socket) {
while(!socket.isClosed) {
//do stuff
}
}
}
}
答案 3 :(得分:0)
简单地说:你不能依赖它。 ExecutorService
只是interrupts正在运行的任务;如果他们真的取消了他们的努力,那就取决于任务的实施。某些I / O可能(并且将会)被中断,尤其是java.nio
内容,但java.io
很可能不会被中断。有关详细说明,请参阅What does java.lang.Thread.interrupt() do?。