多线程之无法抛出InterruptedException异常

郎家岭伯爵 2023年08月08日 599次浏览

问题

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

xxl-job的终止任务功能

但由于我们在代码中通常会加入异常处理机制,导致 xxl-job 抛出的 InterruptedException 异常一并被处理,从而无法手动终止任务。

为了使用手动终止任务的功能,我们需要针对 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 异常包装成其它异常抛出。