2011-07-12 54 views
7

这个片段是从JCIP(作者Brian Goetz)上市6.15为什么恢复线程池中的线程

f.get跑(任务的中断标志)抛出InterruptedException的和为ExecutionException。现在,这些例外情况对未来是否正确? 意味着未来所代表的具体任务被打断或出现内部异常。

问题 -

  1. 为什么我需要恢复使用中断 “Thread.currentThread()中断()。”? ,因为我的任务运行的线程不是中断标志吗?这有点令人困惑。

  2. 为什么抛出launderThrowable异常?如果其中一个downloadImage存在问题,我们是不是应该只处理其他下载的图像,而不是处理剩下的未来?

    package net.jcip.examples; 
    
    import java.util.*; 
    import java.util.concurrent.*; 
    import static net.jcip.examples.LaunderThrowable.launderThrowable; 
    
    /** 
    * Renderer 
    * <p/> 
    * Using CompletionService to render page elements as they become available 
    * 
    * @author Brian Goetz and Tim Peierls 
    */ 
    public abstract class Renderer { 
        private final ExecutorService executor; 
    
        Renderer(ExecutorService executor) { 
         this.executor = executor; 
        } 
    
        void renderPage(CharSequence source) { 
         final List<ImageInfo> info = scanForImageInfo(source); 
         CompletionService<ImageData> completionService = 
           new ExecutorCompletionService<ImageData>(executor); 
         for (final ImageInfo imageInfo : info) 
          completionService.submit(new Callable<ImageData>() { 
           public ImageData call() { 
            return imageInfo.downloadImage(); 
           } 
          }); 
    
         renderText(source); 
    
         try { 
          for (int t = 0, n = info.size(); t < n; t++) { 
           Future<ImageData> f = completionService.take(); 
           ImageData imageData = f.get(); 
           renderImage(imageData); 
          } 
         } catch (InterruptedException e) { 
          Thread.currentThread().interrupt(); 
         } catch (ExecutionException e) { 
          throw launderThrowable(e.getCause()); 
         } 
        } 
    
        interface ImageData { 
        } 
    
        interface ImageInfo { 
         ImageData downloadImage(); 
        } 
    
        abstract void renderText(CharSequence s); 
    
        abstract List<ImageInfo> scanForImageInfo(CharSequence s); 
    
        abstract void renderImage(ImageData i); 
    
    } 
    

回答

1
  1. 中断不一定发生在线程池的线程上。当你在等待未来的完成时,当前的线程被中断时,中断是一个点。例如,如果您让Future的其他部分可以取消下载,则Future.cancel(true)将导致发生InterruptedException,然后您可以清除其余的数据。正如Beohemaian所说,传播中断总是安全的。

  2. 这是一个很好的问题。我认为这更像是他希望做的事情的设计选择。但是,您可以轻松地坚持该错误并在完成其余部分后抛出该错误。有些事情要考虑,但如果它是一个OutOfMemoryError呢?然后,如果它的一个错误,也许不是一个RuntimeException,那么洗涤程序将会很有用。

+0

'错误'应该是不可恢复的东西。 'StackOverflowError'如何?堆栈可能已损坏。 'InternalError'如何?它的虚拟机状态已损坏。你不能抓住他们。 –

+0

是的你是对的。那是我用OutOfMemoryError去的地方。尽管清洗方法也会重新抛出运行时异常(至少在本例中) –

2

通过捕获InterruptedException,你到达中正在运行的线程停止中断。但是你希望它能够达到它,以防在中断的情况下线程需要做特殊处理 - 你不能说出来,所以你最好安全地玩它,让它渗透。你可以自己做一些处理(清理,退出你在做什么等),但你必须传递它。最好的方法是致电Thread.currentThread().interrupt()

3

当你捕获InterruptedException中断标志得到重置,你的线程在技术上不再中断。但是,您不知道调用代码的代码(或同一线程中的其他代码)是否需要额外的中断处理。通过调用interrupt(),您再次提升标志,并有效地对应用程序的其余部分说:“该线程仍然中断 - 如果需要的话执行该线程”。

考虑一下例子。你的方法是从循环中调用的,如果线程中断,它必须终止。你发现了这个异常,如果你不提升这个标志,循环将不会按需要终止。

+0

只需添加更多细节:当Java库中的某些阻塞方法抛出一个'InterruptedException'时,线程的中断标志将重置为false。检查例如['Thread.sleep()']的文档(http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#sleep%28long%29)或['的Object.wait()'](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait%28%29) –