线程池子线程的终止Shutdown()、ShutdownNow()

背景

之前某需求在触发流控时需要中断ExcutorService中的子线程,发现无论Shutdown、ShutdownNow方法都无法直接停止子线程,今天看到线程的interrupt()方法才了解如何停止。

stop() 和 interrupt()

stop方法

stop() 方法会真的杀死线程,不给线程喘息的机会,如果线程持有 ReentrantLock 锁,被 stop() 的线程并不会自动调用 ReentrantLock 的 unlock() 去释放锁,那其他线程就再也没机会获得 ReentrantLock 锁,类似的方法还有 suspend() 和 resume() 方法。故已不建议使用。

interrupt方法

interrupt() 方法仅仅是通知线程,线程有机会执行一些后续操作,同时也可以无视这个通知。

被 interrupt 的线程,是怎么收到通知的呢?一种是异常,另一种是主动检测。

异常

  • 当线程 A 处于 WAITING、TIMED_WAITING 状态时,如果其他线程调用线程 A 的 interrupt() 方法,会使线程 A 返回到 RUNNABLE 状态,同时线程 A 的代码会触发 InterruptedException 异常

  • 当线程 A 处于 RUNNABLE 状态时,并且阻塞在IO上时。如阻塞在java.nio.channels.InterruptibleChannel 上时,如果其他线程调用线程 A 的 interrupt() 方法,线程 A 会触发 java.nio.channels.ClosedByInterruptException 这个异常;而阻塞在 java.nio.channels.Selector 上时,如果其他线程调用线程 A 的 interrupt() 方法,线程 A 的 java.nio.channels.Selector 会立即返回。

tips: 这里的状态为Java线程状态:NEW(初始化状态)RUNNABLE(可运行 / 运行状态)BLOCKED(阻塞状态)WAITING(无时限等待)TIMED_WAITING(有时限等待)TERMINATED(终止状态)

主动检查

线程处于 RUNNABLE 状态,并且没有阻塞在某个 I/O 操作上,得依赖线程 A 主动检测中断状态。

如果其他线程调用线程 A 的 interrupt() 方法,那么线程 A 可以通过 isInterrupted() 方法,检测是不是自己被中断。

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            for (int i = 0; i < 10000000; i++) {
                System.out.println(i);
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("find Interrupted");
                    break;
                }
            }
        });
        ExecutorService executors = Executors.newFixedThreadPool(1);
        // 线程池执行
        System.out.println("excute");
        executors.execute(t);
        // 等待0.5秒
        Thread.sleep(500);
        // 线程池中断
        executors.shutdownNow();
        t.join();
    }
}

如果子线程不检测isInterrupted()并主动停止,那么会继续运行下次。

中断标记与清楚

interrupt()会给对象线程打上中断标记,而捕获InterruptedException异常会清除标记。

Thread.currentThread().isInterrupted()不会清除标记。

shutdown()和shutdownNow()

shutdown方法只会取消等待中的任务,而shutdownNow方法还会给执行中的任务打上中断标记。

posted @ 2023-03-18 17:26  kiper  阅读(136)  评论(0编辑  收藏  举报