在一个线程T1中如何优雅终止线程T2?这里的【优雅】指的是给T2一个料理后事的机会。
package com.xzp.juc.test1;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Test6 {
public static void main(String[] args) throws InterruptedException {
TPTInterrupt tptInterrupt = new TPTInterrupt();
log.debug("开始start");
tptInterrupt.start();
log.debug("结束start");
Thread.sleep(3500);
log.debug("开始stop");
tptInterrupt.stop();
log.debug("结束stop");
}
}
@Slf4j
class TPTInterrupt{
private Thread thread;
public void start() {
thread = new Thread(() -> {
while (true) {
Thread currented = Thread.currentThread();
log.debug("1打断标记{}",currented.isInterrupted());
if(currented.isInterrupted()){
log.debug("料理后事");
break;
}
try {
Thread.sleep(1000);//情况一,这个时候被打断会把打断标记编程假,所以还要执行一次 currented.interrupt();
log.debug("执行监控记录");//情况二,这个时候打断,不会将打断标记变成true,程序继续执行
} catch (InterruptedException e) {
log.debug("2打断标记{}",currented.isInterrupted());
currented.interrupt();
log.debug("3打断标记{}",currented.isInterrupted());
e.printStackTrace();
}
}
},"t1");
thread.start();
}
public void stop() {
log.debug("4打断标记{}",thread.isInterrupted());
thread.interrupt();
log.debug("5打断标记{}",thread.isInterrupted());
}
}
执行逻辑
改进,加入volatile,实现JMM的可见性进行实现,可见性 - 保证指令不会受 cpu 缓存的影响。
@Slf4j
public class Test2 {
public static void main(String[] args) throws InterruptedException {
TwoPhaseTermination tptInterrupt = new TwoPhaseTermination();
log.debug("开始start");
tptInterrupt.start();
log.debug("结束start");
Thread.sleep(3500);
log.debug("开始stop");
tptInterrupt.stop();
log.debug("结束stop");
}
}
@Slf4j
class TwoPhaseTermination{
private Thread monitorThread;
private volatile boolean stop = false;
public void start() throws InterruptedException{
monitorThread =new Thread(() -> {
while (true){
if(stop){
log.debug("料理后事");
break;
}
try {
Thread.sleep(1000);
log.debug("执行监控记录");
}catch (InterruptedException e){
e.printStackTrace();
}
}
},"monitor");
monitorThread.start();
}
public void stop(){
stop = true;
// 防止try里面业务太长,直接打断,节省时间直接处理后事
monitorThread.interrupt();
}
}