问题
今天遇到这样一个问题:我在 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
异常包装成其它异常抛出。