JUC并发编程 -- 线程常用方法之interrupt 方法详解 & 设计模式之两阶段终止 & 打断 park 线程
Posted Z && Y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUC并发编程 -- 线程常用方法之interrupt 方法详解 & 设计模式之两阶段终止 & 打断 park 线程相关的知识,希望对你有一定的参考价值。
1. 线程常用方法之interrupt 方法详解
1.1 打断阻塞方法
- 打断 sleep,wait,join 的线程这几个方法都会让线程进入阻塞状态
打断阻塞的线程,会清空打断状态(打断标记记为false),以 sleep 为例:
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "c.Test11")
public class Test11 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
log.debug("sleep...");
try {
Thread.sleep(5000); // wait, join
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t1");
t1.start();
Thread.sleep(1000);
t1.interrupt();
log.debug("t1 interrupt");
log.debug("打断标记:{}", t1.isInterrupted());
}
}
运行结果:
1.2 打断正常运行的线程
代码:
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "c.Test12")
public class Test12 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true) {
// 正常运行的线程被打断后 该线程的打断标记会设置为true
boolean interrupted = Thread.currentThread().isInterrupted();
if (interrupted) {
log.debug("被打断了, 退出循环");
// 退出循环 因为该线程后面没有代码可以执行了, 所以这里相当于结束行程
break;
}
}
}, "t1");
t1.start();
Thread.sleep(1000);
log.debug("interrupt");
t1.interrupt();
}
}
运行结果:
2. 设计模式之两阶段终止
2.1 原理
在一个线程T1中如何“优雅”终止线程T2?这里的【优雅】指的是给T2一个料理后事的机会。
错误思路:
设计模式之两阶段终止图解:
2.2 两阶段终止-interrupt实现
代码:
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "c.TwoPhaseTermination")
public class Test13 {
public static void main(String[] args) throws InterruptedException {
TwoPhaseTermination tpt = new TwoPhaseTermination();
tpt.start();
Thread.sleep(3500);
log.debug("停止监控");
tpt.stop();
}
}
@Slf4j(topic = "c.TwoPhaseTermination")
class TwoPhaseTermination {
// 监控线程
private Thread monitorThread;
// 启动监控线程
public void start() {
monitorThread = new Thread(() -> {
while (true) {
Thread currentThread = Thread.currentThread();
if (currentThread.isInterrupted()) {
log.debug("料理后事");
break;
}
try {
Thread.sleep(1000);
log.debug("执行监控记录");
} catch (InterruptedException e) {
e.printStackTrace();
// 重新设置打断标记
monitorThread.interrupt();
}
}
}, "monitor");
monitorThread.start();
}
// 停止监控线程
public void stop() {
monitorThread.interrupt();
}
}
运行结果:
3. 打断 park 线程
LockSupport.park()方法是让当前线程进入阻塞状态:
3.1 park 线程展示
示例代码:
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.LockSupport;
@Slf4j(topic = "c.Test14")
public class Test14 {
private static void test3() throws Exception {
Thread t1 = new Thread(() -> {
log.debug("park...");
LockSupport.park();
log.debug("unpark...");
log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
}, "t1");
t1.start();
// Thread.sleep(1000);
// t1.interrupt();
}
public static void main(String[] args) throws Exception {
test3();
}
}
运行结果(发现该线程进入阻塞状态):
3.2 打断park线程
现在的运行结果:
3.3 补充:
打断标记为真的情况下,再次使用park方法不起作用
示例代码:
运行结果:
如何让park方法再次起作用呢?==>重新设置打断标记
现在的运行结果:
以上是关于JUC并发编程 -- 线程常用方法之interrupt 方法详解 & 设计模式之两阶段终止 & 打断 park 线程的主要内容,如果未能解决你的问题,请参考以下文章
JUC并发编程 -- 线程常用方法之sleep() & yield() & 线程优先级 & sleep方法应用: 限制对 CPU 的使用
JUC并发编程 -- 线程常用方法概述 & start() vs run()