我想中断一个线程,该线程正在无限 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/