首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >确保线程被中断

确保线程被中断
EN

Stack Overflow用户
提问于 2018-02-16 23:05:59
回答 2查看 85关注 0票数 0

我想要中断一个线程,该线程在一个无限的while循环的每个增量中检查中断标志。退出循环的唯一方法是抛出InterruptedException。

在可中断线程执行的(不可访问的)代码中的某处,休眠操作声明了一个InterruptedException和一个catch块,其中异常被吞噬。不幸的是,在执行睡眠方法时,线程将被中断,从而导致中断标志被重置。在这种情况下,线程不会退出无限的while循环。

避免这种情况的最佳策略是什么?下面代码中的主线程在循环中调用interrupt,直到可中断线程不再活动为止。这是一个合理的策略吗?有什么替代方案吗?

代码语言:javascript
复制
 public class InterruptableThreads extends Thread {

    public static Thread t1 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                while (true) {

                    if (Thread.currentThread().isInterrupted()) {
                        throw new InterruptedException();
                    }

                    try {
                        Thread.sleep(5000);
                    } catch (Exception e) {
                        System.out.println("Swallowing exception. Resetting interrupted flag");
                    }

                    System.out.println("t1 run");
                }
            } catch (InterruptedException e) {
                System.err.println("t1 interrupted.");
            }
        }

    });

    public static void main(String[] args) throws InterruptedException {

        t1.start();

        Thread.sleep(4000);

        while (t1.isAlive()) {
            t1.interrupt();
        }

        t1.join(1000);

        System.out.println("Finished!");


    }
}
EN

回答 2

Stack Overflow用户

发布于 2018-02-17 23:24:18

你提出的解决方案,包括循环直到线程死亡,应该可以工作。我不知道这是否可能,但您可能希望通过在该循环中包含join语句来避免主动旋转:

代码语言:javascript
复制
    while (t1.isAlive()) {
        t1.interrupt();
        try {
            t1.join(1000);

        } catch(InterruptedException e) {
            ...
        }
    }

另一种方法是将接受中断的代码的执行与可中断线程的主循环隔离开来:

代码语言:javascript
复制
public static Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<?> f = null;

        try {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    throw new InterruptedException();
                }

                f = executor.submit(new Runnable() {
                    // swallowing code
                });

                try {
                   f.get();

                } catch(CancellationException e) {
                  ...
                } catch(ExecutionException e) {
                  ...
                } // interrupted exceptions will be thrown from get() but not caught here                 

                System.out.println("t1 run");
            }
        } catch (InterruptedException e) {
            System.err.println("t1 interrupted.");
            if (f != null) {
              f.cancel(true);
            }

        } finally {
            executor.shutdownNow();
        }
    }

});

f.get()将使您有可能捕获t1的中断,而不管由executor服务启动的线程的状态如何,在该状态下,外部代码将被执行,并且可能处于“睡眠”状态。

但添加另一个线程会带来额外的复杂性和相关的风险。

票数 1
EN

Stack Overflow用户

发布于 2018-02-16 23:20:45

Brian Goetz在《实践中的Java并发》一书中概述了最佳策略。在内存中,您可以从catch块中重新中断线程,或者抛出异常。

另外,尽可能捕获最窄的异常,而不是Exception

代码语言:javascript
复制
                if (Thread.currentThread().isInterrupted()) {
                    throw new InterruptedException();
                }

                try {
                    Thread.sleep(5000);
                } catch (InterrutedException e) {         // <---- Narrow the scope here
                    System.out.println("Swallowing exception. Resetting interrupted flag");
                    Thread.currentThread().interrupt();   // <----- NEW
                }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48829549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档