2013-04-29 126 views
2

我正在使用Executors进行线程池和提交任务。 executorService.shutdownNow是否可以关闭所有任务,即使它们中的一些可能会在对数据库或套接字的I/O调用时被阻止?执行器shutdownNow被阻塞的任务?

回答

4

这取决于你的任务是否写得很好!

documentation说:“shutdown()方法将允许先前提交的任务在终止前执行,而shutdownNow()方法阻止等待任务启动并尝试停止当前正在执行的任务。

但是,Java并没有“无中生有”地杀死线程。它试图中断他们。当shtudownNow尝试中断它们并优雅地结束时,一个好的任务会抛出某种InterruptException。你提到套接字通信 - 大多数体面的客户端的阻塞方法如果中断,会抛出一个中断的异常。

一个不好的任务的例子可能(很明显)用while(true) { readChunk(); if(endOfChunks) { break;} }运行一个线程。这不提供优雅的中断检查!这是旧规则,不使用while循环等待,而是使用syncronized上的'阻断器'对象来阻止wait()

+0

终止的唯一方法是作为子进程而不是子线程运行。过程可以终止。 – gpa 2013-04-29 16:44:15

1

不,没有保证。如果您看到ExecutorService#shutdownNow的API文档。它说,

除了竭尽全力尝试停止处理主动执行的任务之外,没有任何保证。

如果要阻止,直到关闭请求后的所有任务都已完成执行,请使用ExecutorService#awaitTermination

+0

是 - awaitTermination是理想的选择。 – Tom 2013-04-29 16:41:21

0

简而言之:你不能依赖那个。 ExecutorService只是interrupts的运行任务;如果他们真的取消了他们的努力,那么这些任务就要执行了。一些I/O可能(也将会)被中断,尤其是java.nio的东西,但java.io很可能不会中断。有关更多解释,请参阅What does java.lang.Thread.interrupt() do?

1

当无法处理中断(java.io)时,需要使用非标准关闭逻辑。

我对封装这个问题的解决方案结合了来自'Java Concurrency In Practice'的示例'TrackingExecutorService'和'SocketUsingTask'。

  • 定义“Shutdownable”界面
  • 扩展的ThreadPoolExecutor跟踪运行实现了“Shutdownable”界面提交任务
  • 覆盖的ThreadPoolExecutor的shutdownNow时通过“Shutdownable”接口调用非标准关机逻辑


    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 
       } 
      } 
     } 
    }