Java中断

2021-12-12  本文已影响0人  lz做过前端
线程状态转换图

概述

中断是一种线程同步方式

public class InterruptBeforeBlocking {

    public static void main(String[] args) {

        Object o = new Object();

        Thread thread = new Thread(() -> {
            synchronized (o) {
//                for (int i = 0; i < 10000; i++) {
//                    System.out.println("for (int i = 0; i < 10000; i++)");
//                }
                // interrupted 会重置打断标志
//                while (!Thread.interrupted()) {
//                    System.out.println("while interrupted is false");
//                }
                // 不会重置
                while (!Thread.currentThread().isInterrupted()) {
                    System.out.println("while isInterrupted is false");
                }
                System.out.println("exist from loop");
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    System.out.println("interrupted is " + Thread.interrupted());
//                    System.out.println("isInterrupted is " + Thread.currentThread().isInterrupted());
                    System.out.println("InterruptedException");
                }
            }
        });
        thread.start();
        System.out.println("main interrupt begin");
        thread.interrupt();
        System.out.println("main interrupt end");
    }
}

中断标志

Thread.interrupted() 与 thread.isInterrupted()

thread.interrupt()

public class InterruptNeedReleaseLock {

    public static void main(String[] args) throws InterruptedException {

        Object o = new Object();

        Thread thread = new Thread(() -> {
            synchronized (o) {
                // 这里导致锁不释放,主线程不会触发打断
//                while (!Thread.currentThread().isInterrupted()) {
//                    System.out.println("while isInterrupted is false");
//                }
                System.out.println("exist from loop");
                try {
                    o.wait();
                } catch (InterruptedException e) {
//                    System.out.println("interrupted is " + Thread.interrupted());
                    System.out.println("isInterrupted is " + Thread.currentThread().isInterrupted());
                    // 如果不知道做什么设置为true,让外部Thread.currentThread().isInterrupted()获取打断状态
                    Thread.currentThread().interrupt();
                    System.out.println("isInterrupted is " + Thread.currentThread().isInterrupted());
                    System.out.println("InterruptedException");
                }
            }
        });
        thread.start();
        // 让 thread 先拿到锁
        Thread.sleep(3000);
        synchronized (o) {
            System.out.println("main interrupt begin");
            thread.interrupt();
            // 这里导致锁不被释放,即使thread被打算也不会执行异常后续的代码
            // 所以打断也是先把thread移至等待队列,而只有锁被释放后,才会从等待队列移至同步队列
            // 竞争获取到锁后才会执行异常后续的代码
            for (; ; ) {
            }
//            System.out.println("main interrupt end");
        }

    }
}

中断I/O操作

不可中断

public class LockInterrupt {

    public static void main(String[] args) throws InterruptedException {

        Lock lock = new ReentrantLock();

        Thread thread = new Thread(() -> {
            System.out.println("thread run");
            // 让主线程先执行打断
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("while isInterrupted is false");
            }
            System.out.println("thread will lock.lock");
            lock.lock();
            System.out.println("thread in lock.lock");
            lock.unlock();
            System.out.println("thread lock.lock out");
        });
        thread.start();
        // 让thread先运行
        Thread.sleep(5);
        lock.lock();
        System.out.println("main thread lock.lock in");
        thread.interrupt();
//        lock.unlock();
//        System.out.println("main thread lock.lock out");
        for (; ; ) {
            //
        }
//        lock.unlock();
//        System.out.println("main thread lock.lock out");
    }
}

线程为何可以被中断,即中断的响应

回顾下之前讲的object.wait(long timeout)thread.sleep(long millis)LockSupport.park()的JVM实现

即:线程上的ParkEvent、SleepEvent、parker对象锁

而thread.interrupt()方法的JVM实现,做了以下事情

所以thread.interrupt()可以打断借由线程上的ParkEvent、SleepEvent、parker对象阻塞的线程,即object.wait(long timeout)thread.sleep(long millis)LockSupport.park(),同时这些实现都申明在打断标志设置为true后会抛出InterruptException异常,所以这些方法会再打断执行以及竞争获取到锁后跳转到异常处理处继续执行

线程状态转换
上一篇下一篇

猜你喜欢

热点阅读