java - 如何在 Java 中以原因中断线程/未来/执行程序?
问题描述
我想知道为什么给定线程被中断。它是否被我(我的代码的一部分)、其他库或任何其他原因打断了?
现在我可以通过
Thread.interrupt()
取消未来
Future.cancel(boolean mayInterruptIfRunning)
通过以下方式关闭 Executor
ExecutorService.shutdown() or ExecutorService.shutdownNow()
但是,他们都没有给我发送原因的选项(执行中断的信息)。换句话说,我不能用更详细的消息或原因抛出和捕获 InterruptedException。
编辑:基于 Glains 解决方案,我准备了一个类似的解决方案,但使用了 Callable
public class MyCallable<T> implements Callable<T> {
private final Callable<T> callable;
private volatile Thread thread;
private volatile String interruptReason;
public MyCallable(final Callable<T> callable) {
this.callable = callable;
this.thread = null;
}
@Override
public T call() throws Exception {
this.thread = Thread.currentThread(); // not getCurrentThread()
try {
return callable.call();
}
catch (InterruptedException e) {
System.out.println("Thread is interrupted: " + this.interruptReason);
}
}
public void interrupt(String interruptReason) {
this.interruptReason = interruptReason;
thread.interrupt();
}
}
解决方案
您必须为此编写自定义 API,因为Thread
无法因特定原因中止。为了Runnable
能够被打断,您可以创建一个提供此功能的自定义界面:
public interface Interruptable {
default void interrupt() {
interrupt(Reason.unknown());
}
void interrupt(Reason reason);
}
定义的原因可以是任何东西,但以下可能适合您的用例:
public class Reason {
public static Reason unknown() {
return new Reason("unknown");
}
private final String reason;
public Reason(String reason) {
this.reason = reason;
}
public String getReason() {
return reason;
}
}
现在,您将不得不调整您的Runnable
实现,以便它可以被中断。请注意,以下解决方案优雅地中断了线程,这意味着当前迭代将完成,但不会开始新的迭代。如果要真正中断线程,则需要存储对执行Runnable
实例run
方法的线程的引用,因为interrupt
不会从同一个线程调用该方法。然后,您可以调用Thread.interrupt
该参考。
public class MyRunnable implements Runnable, Interruptable {
private final AtomicBoolean running = new AtomicBoolean(false);
@Override
public void interrupt(Reason reason) {
running.set(false);
System.out.println("Thread is interrupted: " + reason.getReason());
}
@Override
public void run() {
running.set(true);
while (running.get()) {
// do work
}
}
}
推荐阅读
- c# - Caliburn Micro,Wpf 绑定嵌套模型
- java - 我自己的 ArrayAdapter 中出现奇怪的 NullPointerException
- machine-learning - 哪个分类器可以根据非轴平行决策边界进行分类?
- angular - 移动项目文件后模态错误
- c - Flex/Bison 启动条件
- javascript - Angular - 查看父组件中的变量变化
- xml - XML Schema 验证错误:以
- database - 使用 mongodb 的聊天应用程序架构
- mathematical-optimization - PuLP的set partition例子好像做的太多了?
- sql-server - 查找、分组和计算加权平均值?