合理打断处于阻塞的线程状态

一、方法

方法名static功能说明注意
run()新线程启动后会 调用的方法,线程之间串行如果在构造 Thread 对象时传递了 Runnable 参数,则 线程启动后会调用 Runnable 中的 run 方法,否则默 认不执行任何操作。但可以创建 Thread 的子类对象, 来覆盖默认行为
join()等待线程运行结束
join(long n)等待线程运行结 束,最多等待 n 毫秒
isInterrupted()判断是否被打 断,不会清除 打断标记
interrupt()打断线程如果被打断线程正在 sleep,wait,join 会导致被打断 的线程抛出 InterruptedException,并清除 ;如果打断的正在运行的线程,不会清除 ;park 的线程被打断,也会设置 打断标记,不会清除
interrupted()static判断当前线程是 否被打断会清除 打断标记
currentThread()static获取当前正在执 行的线程
sleep(long n)static让当前执行的线 程休眠n毫秒, 休眠时让出 cpu 的时间片给其它 线程

二、使用

1. 打断 sleep,wait,join 的线程

这几个方法都会让线程进入阻塞状态
打断 sleep 的线程, 会清空打断状态,以 sleep 为例

Thread t1 = new Thread(()-> {
    //sleep(1);
    
    //try {
    //    Thread.currentThread().join();
    //} catch (InterruptedException e) {
    //    e.printStackTrace();
    //}
    
    try {
        Thread.currentThread().wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    
}, "t1");
t1.start();
sleep(0.5);
t1.interrupt();
log.debug(" 打断状态: {}", t1.isInterrupted());

输出

sleep:

java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at cn.itcast.n2.util.Sleeper.sleep(Sleeper.java:8)
at cn.itcast.n4.TestInterrupt.lambda$test1$3(TestInterrupt.java:59)
at java.lang.Thread.run(Thread.java:745)
21:18:10.374 [main] c.TestInterrupt - 打断状态: false

wait:

Exception in thread "t1" java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at cn.itcast.test.Test.lambda$main$0(Test.java:30)
	at java.lang.Thread.run(Thread.java:748)
15:37:32.974 c.Test [main] -  打断状态: false

join:

java.lang.InterruptedException
	at java.lang.Object.wait(Native Method)
	at java.lang.Thread.join(Thread.java:1252)
	at java.lang.Thread.join(Thread.java:1326)
	at cn.itcast.test.Test.lambda$main$0(Test.java:25)
	at java.lang.Thread.run(Thread.java:748)
15:46:22.178 c.Test [main] -  打断状态: false

2. 打断正常运行的线程

打断正常运行的线程, 不会清空打断状态

private static void test2() throws InterruptedException {
    Thread t2 = new Thread(()->{
        while(true) {
            Thread current = Thread.currentThread();
            boolean interrupted = current.isInterrupted();
            if(interrupted) {
                log.debug(" 打断状态: {}", interrupted);
                break;
            }
    	}
    }, "t2");
    t2.start();
    sleep(0.5);
    t2.interrupt();
}  

输出

20:57:37.964 [t2] c.TestInterrupt - 打断状态: true  

3. 打断 park 线程

打断 park 线程, 不会清空打断状态

private static void test3() throws InterruptedException {
    Thread t1 = new Thread(() -> {
        log.debug("park...");
        LockSupport.park();
        log.debug("unpark...");
        log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
    }, "t1");
    t1.start();
    sleep(0.5);
    t1.interrupt();
}

输出

21:11:52.795 [t1] c.TestInterrupt - park...
21:11:53.295 [t1] c.TestInterrupt - unpark...
21:11:53.295 [t1] c.TestInterrupt - 打断状态:true

如果打断标记已经是 true, 则 park 会失效

private static void test4() {
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 5; i++) {
            log.debug("park...");
            LockSupport.park();
            log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
        }
        // 清除 打断标记,即 设置为 false
        Thread.interrupted();
        log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
        log.debug("park...");
        LockSupport.park();
        log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
    });
    t1.start();
    sleep(1);
    t1.interrupt();
}

输出

15:54:57.684 c.Test [Thread-0] - park...
15:54:58.692 c.Test [Thread-0] - 打断状态:true
15:54:58.696 c.Test [Thread-0] - park...
15:54:58.696 c.Test [Thread-0] - 打断状态:true
15:54:58.696 c.Test [Thread-0] - park...
15:54:58.696 c.Test [Thread-0] - 打断状态:true
15:54:58.696 c.Test [Thread-0] - park...
15:54:58.696 c.Test [Thread-0] - 打断状态:true
15:54:58.696 c.Test [Thread-0] - park...
15:54:58.696 c.Test [Thread-0] - 打断状态:true
15:54:58.696 c.Test [Thread-0] - 打断状态:false
15:54:58.696 c.Test [Thread-0] - park...
# 还有 下一句打断标记没打印出来,此时已恢复 park 功能

提示
可以使用 Thread.interrupted() 清除打断状态

总结:

  • 处于sleepjoinwait 状态的线程 使用 interrupt() 会清除打断标记 Thread.currentThread().isInterrupted())

  • 处于parkrun 的线程,使用 interrupt()不会清除打断标记 Thread.currentThread().isInterrupted())

  • park线程 调用 interrupt()后,该线程后面再使用的 park会失效,需要使用 Thread.interrupted() 恢复park 为有效

三、结束语

评论区可留言,可私信,可互相交流学习,共同进步,欢迎各位给出意见或评价,本人致力于做到优质文章,希望能有幸拜读各位的建议!

专注品质,热爱生活。
交流技术,奢求同志。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嗝屁小孩纸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值