java - 确保线程被中断

标签 java multithreading concurrency

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

在可中断线程执行的(不可访问的)代码中的某个位置, sleep 操作正在声明 InterruptedException 和一个捕获异常的 catch block 。在不幸的情况下,线程将在执行 sleep 方法时被中断,导致中断标志被重置。在这种情况下,线程不会退出无限的 while 循环。

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

 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!");


    }
}

最佳答案

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

    while (t1.isAlive()) {
        t1.interrupt();
        try {
            t1.join(1000);

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

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

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 的中断,无论外部代码所在的执行程序服务启动的线程的状态如何被执行并可能“hibernate ”。

但是添加另一个线程会带来额外的复杂性以及与之相关的风险。

关于java - 确保线程被中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48829549/

相关文章:

java - 关闭随机 'PopUps'

java - 如何在java中正确编写带有if条件的sql查询

c# - ReaderWriterLockSlim 和计时器

Android - 跟踪线程

用于并行化非线程安全 C++ 库的 Haskell 框架

同时更新结构的不同字段——安全吗?

java - 尝试将文本和blob从mysql检索到jtable

java - izpack 安装程序未实例化

c# - 当我没有可用的控件时如何调用()

java - 为什么并发练习书中的SafePoint类标记为@ThreadSafe?