在java中,阻塞的线程可以打断后继续执行,线程打断前后会有一个打断状态的变化,这个状态会影响park方法的使用,本文主要介绍java打断状态相关的内容。
1、打断阻塞的线程
线程阻塞有很多情况,比如没有获取到锁、执行sleep、执行join等,下面以sleep为例:
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
System.out.println("02-------线程t1被打断");
e.printStackTrace();
}
System.out.println("03--t1的打断状态-:"+Thread.currentThread().isInterrupted());
//开始循环,直到线程被打断后,打断标记变为true才停止
for (;;){
if (Thread.currentThread().isInterrupted())
break;
}
System.out.println("04-------t1的打断状态-:"+Thread.currentThread().isInterrupted());
System.out.println("05--t1的打断状态-:"+Thread.interrupted());
//继续瞓5s
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("06----Thread.interrupted()过后---t1的打断状态-:"+Thread.currentThread().isInterrupted());
System.out.println("07-------t1 over");
}, "t1");
//启动线程t1
t1.start();
TimeUnit.SECONDS.sleep(2);
System.out.println("01--t1的打断状态-:"+t1.isInterrupted());
//打断sleep阻塞状态的线程
t1.interrupt();
TimeUnit.SECONDS.sleep(2);
//打断非阻塞状态的线程
t1.interrupt();
//输出
01--t1的打断状态-:false
02-------线程t1被打断
03--t1的打断状态-:false
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 com.iwat.arithmetic.leetcode.Q452.lambda$main$0(Q452.java:44)
at java.lang.Thread.run(Thread.java:748)
04-------t1的打断状态-:true
05--t1的打断状态-:true
06----Thread.interrupted()过后---t1的打断状态-:false
07-------t1 over
方法介绍:
- interrupt():打断某一线程,
- 如果线程阻塞==(sleep、join、await没有结束,任务调度器不会考虑阻塞的线程)==,会抛出异常。并且将线程的阻塞标记改为false,然后继续运行。注意:锁的作用时阻塞进程,阻塞进程有很多种方式,无论什么原因造成的阻塞,任务调度器都不会考虑阻塞的线程
- 如果线程正常运行,会将线程的阻塞标记改为ture,然后继续运行。
- isInterrupted():返回当前线程的打断标记
- static interrupted():返回当前线程的打断标记,同时将打断标记改为false(只能在线程内部执行),方法如下:
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
线程的打断状态变化:
- 默认时false
- 阻塞被打断仍是false
- 非阻塞状态执行interrupt(),阻塞状态变为true
- 执行static interrupted(),阻塞状态变为false
2、park方法的使用
LockSupport.park()会阻塞线程,生效的条件时阻塞状态为false,当阻塞状态为true时,方法无效无法阻塞线程。
Thread t1 = new Thread(()->{
log.info("01------parking...");
LockSupport.park();
log.info("02------unpark");
log.info("03------t1的打断状态"+Thread.currentThread().isInterrupted());
//如果打断标记已经是 true, 则 park 会失效
LockSupport.park();
log.info("04-------unpark");
},"t1");
t1.start();
TimeUnit.SECONDS.sleep(3);
log.info("t1的打断状态"+t1.isInterrupted());
//打断park
t1.interrupt();
//输出
2023-03-04 08:36:46.518 [t1] INFO -- 01------parking...
2023-03-04 08:36:49.522 [main] INFO -- t1的打断状态false
2023-03-04 08:36:49.522 [t1] INFO -- 02------unpark
2023-03-04 08:36:49.522 [t1] INFO -- 03------t1的打断状态true
2023-03-04 08:36:49.523 [t1] INFO -- 04-------unpark
从打印时间可以看到第二个park没有生效。