java中线程的打断interrupt

128 阅读4分钟

1、interrupt相关的三个方法:

 //Thread.java  
 public void interrupt()            //t.interrupt() 打断t线程(设置t线程某给标志位f=true,并不是打断线程的运行)
 public boolean isInterrupted()     //t.isInterrupted() 查询打断标志位是否被设置(是不是曾经被打断过)
 public static boolean interrupted()//Thread.interrupted() 查看“当前”线程是否被打断,如果被打断,恢复标志位
  1. interrupt() :实例方法,设置线程中断标志
  • interrupt()方法是Thread类的实例方法,用于中断当前线程或指定线程。
  • 调用interrupt()方法会将线程的中断状态设置为true
  • 如果线程处于阻塞状态(如sleepwaitjoin等),那么调用interrupt()方法会立即抛出InterruptedException异常。
  • 如果线程处于非阻塞状态,interrupt()方法仅会将线程的中断状态设置为true,具体的中断行为需要线程自行处理。
  1. isInterrupted():实例方法
  • isInterrupted()方法是Thread类的实例方法,用于检查线程的中断状态。
  • 调用isInterrupted()方法会返回线程的中断状态,即是否被中断。
  • 该方法不会清除线程的中断状态。
  1. interrupted():静态方法
  • interrupted()方法是Thread类的静态方法,用于检查当前线程的中断状态,并且会清除中断状态。
  • 调用interrupted()方法会返回当前线程的中断状态,即是否被中断。
  • isInterrupted()方法不同,interrupted()方法会清除当前线程的中断状态。

2、准备工具类,控制线程的睡眠时间

public static class SleepHelper {
    public static void sleepSeconds(int seconds) {
        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void sleepMilli(int i) {
        try {
            TimeUnit.MILLISECONDS.sleep(i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

3、知识点讲解及代码示例

1)、interrupt方法的使用和interrupted的使用

//===================================================

// 打断某个线程,设置标志位
Thread t1 = new Thread(()->{
    for (;;){
        if (Thread.currentThread().isInterrupted()){
            System.out.println("Thread is interrupted! now State is " + Thread.currentThread().getState());
            System.out.println(Thread.currentThread().isInterrupted());
            break;
        }
    }
});

t1.start();

SleepHelper.sleepSeconds(2);

t1.interrupt();

//===================================================

// interrupted检查线程是否打断过,
// 如果打断过,重置标志位
Thread t2 = new Thread(() -> {
    for (; ; ) {
        if (Thread.interrupted()) {
            System.out.println("Thread is interrupted!");
            System.out.println(Thread.interrupted());
        }
    }
});

t2.start();

SleepHelper.sleepSeconds(2);

t2.interrupt();

// 如果在这里写
// 输出的是主线程的中断状态
System.out.println("main: " + t2.interrupted());

2)、interrupt和sleep() wait() join()

sleep()方法在睡眠的时候,不到时间是没有办法叫醒的,这个时候可以用interrupt设置标志位,然后必须catch InterruptedException来进行处理,决定继续睡或者是别的逻辑,(自动进行中断标志复位)

  • 下方是代码示例
//===================================================

// interrupt不能打断进程的sleep状态
// 必须得catch InterruptedException来进行处理,决定继续睡或者是别的逻辑,(自动进行中断标志复位)
Thread t3 = new Thread(() -> {
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        System.out.println("Thread is interrupted!");
        System.out.println(Thread.currentThread().isInterrupted());
    }
});

t3.start();

SleepHelper.sleepSeconds(5);

t3.interrupt();

//===================================================

// interrupt不能打断进程的wait状态
// 必须得catch InterruptedException来进行处理,决定继续睡或者是别的逻辑,(自动进行中断标志复位)

Thread t4 = new Thread(() -> {
    synchronized (o) {
        try {
            o.wait();
        } catch (InterruptedException e) {
            System.out.println("Thread is interrupted!");
            System.out.println(Thread.currentThread().isInterrupted());
        }
    }
});

t4.start();

SleepHelper.sleepSeconds(5);

t4.interrupt();

3)、interrupt不能中断正在竞争锁的线程

//===================================================

// interrupt不能中断正在竞争锁的线程
// 下面证明interrupt不能中断正在synchronized竞争锁的线程
Thread t5_1 = new Thread(() -> {
    synchronized (o) {
        SleepHelper.sleepSeconds(10);
    }
});

t5_1.start();

SleepHelper.sleepSeconds(1);

Thread t5_2 = new Thread(() -> {
    synchronized (o) {

    }
    System.out.println("t2 end!");
});

t5_2.start();

SleepHelper.sleepSeconds(1);

t5_2.interrupt();

//===================================================

// interrupt不能中断正在竞争锁的线程
// 下面证明interrupt不能中断正在lock竞争锁的线程
Thread t6_1 = new Thread(() -> {
    lock.lock();
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
    System.out.println("t1 end!");
});

t6_1.start();

SleepHelper.sleepSeconds(1);


Thread t6_2 = new Thread(() -> {
    lock.lock();
    try {
    } finally {
        lock.unlock();
    }
    System.out.println("t2 end!");
});

t6_2.start();

SleepHelper.sleepSeconds(1);

t6_2.interrupt();

4)、如果想打断正在竞争锁的线程,使用ReentrantLock的lockInterruptibly()

//===================================================
// 如果想打断正在竞争锁的线程,使用ReentrantLock的lockInterruptibly()

Thread t7_1 = new Thread(() -> {
    lock.lock();
    try {
        SleepHelper.sleepSeconds(10);
    } finally {
        lock.unlock();
    }
    System.out.println("t1 end!");
});

t7_1.start();

SleepHelper.sleepSeconds(1);


Thread t7_2 = new Thread(() -> {
    System.out.println("t2 start!");
    try {
        lock.lockInterruptibly();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
    System.out.println("t2 end!");
});

t7_2.start();

SleepHelper.sleepSeconds(1);

t7_2.interrupt();

5)、整体代码

public static void main(String[] args) throws Exception {
        
        Object o = new Object();
        ReentrantLock lock = new ReentrantLock();
        //===================================================
        // 打断某个线程,设置标志位
        Thread t1 = new Thread(()->{
            for (;;){
                if (Thread.currentThread().isInterrupted()){
                    System.out.println("Thread is interrupted! now State is " + Thread.currentThread().getState());
                    System.out.println(Thread.currentThread().isInterrupted());
                    break;
                }
            }
        });

        t1.start();

        SleepHelper.sleepSeconds(2);

        t1.interrupt();

        //===================================================
        // interrupted检查线程是否打断过,
        // 如果打断过,重置标志位
        Thread t2 = new Thread(() -> {
            for (; ; ) {
                if (Thread.interrupted()) {
                    System.out.println("Thread is interrupted!");
                    System.out.println(Thread.interrupted());
                }
            }
        });

        t2.start();

        SleepHelper.sleepSeconds(2);

        t2.interrupt();

        // 如果在这里写
        // 输出的是主线程的中断状态
        System.out.println("main: " + t2.interrupted());

        //===================================================
        // interrupt不能打断进程的sleep状态
        // 必须得catch InterruptedException来进行处理,决定继续睡或者是别的逻辑,(自动进行中断标志复位)
        Thread t3 = new Thread(() -> {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                System.out.println("Thread is interrupted!");
                System.out.println(Thread.currentThread().isInterrupted());
            }
        });

        t3.start();

        SleepHelper.sleepSeconds(5);

        t3.interrupt();

        //===================================================
        // interrupt不能打断进程的wait状态
        // 必须得catch InterruptedException来进行处理,决定继续睡或者是别的逻辑,(自动进行中断标志复位)

        Thread t4 = new Thread(() -> {
            synchronized (o) {
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    System.out.println("Thread is interrupted!");
                    System.out.println(Thread.currentThread().isInterrupted());
                }
            }
        });

        t4.start();

        SleepHelper.sleepSeconds(5);

        t4.interrupt();

        //===================================================
        // interrupt不能中断正在竞争锁的线程
        // 下面证明interrupt不能中断正在synchronized竞争锁的线程
        Thread t5_1 = new Thread(() -> {
            synchronized (o) {
                SleepHelper.sleepSeconds(10);
            }
        });

        t5_1.start();

        SleepHelper.sleepSeconds(1);

        Thread t5_2 = new Thread(() -> {
            synchronized (o) {

            }
            System.out.println("t2 end!");
        });

        t5_2.start();

        SleepHelper.sleepSeconds(1);

        t5_2.interrupt();

        //===================================================
        // interrupt不能中断正在竞争锁的线程
        // 下面证明interrupt不能中断正在lock竞争锁的线程
        Thread t6_1 = new Thread(() -> {
            lock.lock();
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            System.out.println("t1 end!");
        });

        t6_1.start();

        SleepHelper.sleepSeconds(1);


        Thread t6_2 = new Thread(() -> {
            lock.lock();
            try {
            } finally {
                lock.unlock();
            }
            System.out.println("t2 end!");
        });

        t6_2.start();

        SleepHelper.sleepSeconds(1);

        t6_2.interrupt();


        //===================================================
        // 如果想打断正在竞争锁的线程,使用ReentrantLock的lockInterruptibly()

        Thread t7_1 = new Thread(() -> {
            lock.lock();
            try {
                SleepHelper.sleepSeconds(10);
            } finally {
                lock.unlock();
            }
            System.out.println("t1 end!");
        });

        t7_1.start();

        SleepHelper.sleepSeconds(1);


        Thread t7_2 = new Thread(() -> {
            System.out.println("t2 start!");
            try {
                lock.lockInterruptibly();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            System.out.println("t2 end!");
        });

        t7_2.start();

        SleepHelper.sleepSeconds(1);

        t7_2.interrupt();
    }