在Java中,我如何用理性中断线程/未来/执行器



我想知道给定线程被中断的原因。它是被我(我的代码的一部分(、其他库或任何其他原因打断的吗?

现在我可以通过中断线程

Thread.interrupt()

通过取消未来

Future.cancel(boolean mayInterruptIfRunning)

关闭执行程序

ExecutorService.shutdown() or ExecutorService.shutdownNow()

但是,它们都没有给我发送原因(执行中断的信息(的选项。换句话说,我不能抛出并捕获具有更详细消息或原因的InterruptedException。

编辑:基于Glains解决方案,我准备了一个类似的解决方案,但使用了可调用

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
}
}
}

最新更新