问题
今天遇到这样一个问题:我在 XXL-JOB 中设置了一个定时任务,并且在这个任务中使用了多线程。在 xxl-job 启动任务后,有一个手动终止任务的功能,点击“终止任务”后 xxl-job 会在程序中抛一个 InterruptedException 异常来终止程序。

但由于我们在代码中通常会加入异常处理机制,导致 xxl-job 抛出的 InterruptedException 异常一并被处理,从而无法手动终止任务。
为了使用手动终止任务的功能,我们需要针对 InterruptedException 异常做特殊处理(也就是如果是 InterruptedException 异常就抛出),但在抛出 InterruptedException 异常时提示编译报错。

解决
问题原因
多线程不允许抛出 InterruptedException 异常。
为什么多线程不允许抛出 InterruptedException 异常?
Runnable接口的run方法不允许抛出InterruptedException是因为在设计Runnable接口时,Java 的设计者可能考虑了多种使用场景和线程模型,以确保线程的可控性和一致性。
问题解决
对于实现了 Runnable 接口的任务,在其 run 方法中抛出异常时,通常需要使用 try-catch 块捕获异常。InterruptedException 是一个特殊的异常,通常需要在处理线程中断的情况下使用。以下是如何在 run 方法中处理InterruptedException 并传递异常的示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author 郎家岭伯爵
*/
public class Test {
public static void main(String[] args){
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(() -> {
try {
for (int i = 0; i < 50; i++) {
test(i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 重新设置中断状态
throw new RuntimeException(e); // 将InterruptedException包装成RuntimeException传递出去
}
});
executorService.shutdown();
}
public static void test(int i) throws InterruptedException {
System.out.println(i);
if (i == 15) {
throw new InterruptedException("线程中断异常");
}
}
}
在上面的代码中,首先捕获了 InterruptedException,然后通过调用 Thread.currentThread().interrupt() 来重新设置线程的中断状态,以便上层调用者可以检查中断状态。接下来,我们将捕获到的 InterruptedException 包装成 RuntimeException 并抛出,以便异常可以传递到调用者处。
Thread.currentThread().interrupt();:把线程的中断状态重新设置为 true,这样在上层调用者中可以通过 Thread.currentThread().isInterrupted() 方法来检查中断状态,从而进行适当的处理。
总结
多线程不允许抛出 InterruptedException 异常。 在多线程环境下通常我们可以把 InterruptedException 异常包装成其它异常抛出。