为什么要恢复在线程池的线程中运行的任务的中断标志

时间:2011-07-12 00:14:55

标签: java concurrency

此片段来自JCIP(Brian Goetz),列出6.15

f.get()抛出InterruptedException和ExecutionException。现在,这些例外是否具体到未来正确? 意味着未来所代表的特定任务被中断或有内部例外。

问题 -

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

  2. 为什么要抛出washderThrowable异常?如果其中一个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);
    
    }
    

3 个答案:

答案 0 :(得分:3)

通过捕获InterruptedException,您可以阻止中断到达正在运行的线程。但是你希望它能够达到它,以防万一中断时线程需要做任何特殊处理 - 你无法分辨,所以你最好安全地玩它并允许它渗透。你可以自己做一些处理(清理,退出你正在做的事情等),但你必须将它传递给你。最好的方法是拨打Thread.currentThread().interrupt()

答案 1 :(得分:3)

当您捕获InterruptedException时,中断标志会被重置,并且您的线程在技术上不会再被中断。但是,您不知道调用代码的代码(或同一线程中的其他代码)是否需要任何其他中断处理。通过调用interrupt(),你再次举起标志并有效地向应用程序的其余部分说“这个线程仍然被中断 - 必要时对它进行操作”。

考虑一下例子。如果线程被中断,则必须从循环中调用您的方法。您捕获了异常,如果您没有引发该标志,则循环将不会根据需要终止。

答案 2 :(得分:1)

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

  2. 这是个好问题。我认为这更像是他想要它做的设计选择。但是你可以很容易地抓住那个错误并在完成剩下的工作后抛出它。但要考虑一下,如果它是一个OutOfMemoryError怎么办?然后,只有当它出现错误并且可能不是Ru​​ntimeException时,清洗才有用。