使用volatile实现直接不使用打断标记,而是通过一个stop变量实现线程打断效果,当调用stop方法时,会将stop值设为true,监控线程会时刻监视stop的值,但是这种“假打断”的方式会有缺点,当线程执行到sleep时,虽然stop值已经置为true,但是还是需要等待sleep执行结束,开始执行下一次循环的时候才能退出,所以可以调用interrupt方法真正的打断,这种情况仔细考虑下其实做法很巧妙,如果监控线程正常运行,那么interrupt方法打断只是改变了打断标记,不做处理即可,因为本例的业务逻辑也不涉及利用打断标记。而如果确实是在sleep过程中被打断,那么会进入catch块中,catch块不做处理即可,还是会进入下一次循环。
public class TestTwoPhases {public static void main(String[] args) throws InterruptedException {TwoPhaseTermination tpt = new TwoPhaseTermination();//创建线程,监控该线程状态,tpt.start();Thread.sleep(3500);//停止线程,但优雅地停止,选择interrupt线程;tpt.stop();}}//监控类class TwoPhaseTermination{private Thread monitor;private volatile boolean stop = false;//判读是否应该打断,不采用打断标记的形式//启动监控线程public void start(){//java基础,调用start方法,这里的monitor即指当前对象的monitor属性,与this.monitor等价monitor = new Thread(()->{while(true){if(stop){//stop为真,代表确实应该中断System.out.println("料理后事");break;}try {Thread.sleep(1000);//打断情况1System.out.println("执行监控记录");//打断情况2} catch (InterruptedException e) {}}});monitor.start();}// 停止监控线程public void stop(){stop=true;//应该打断monitor.interrupt();//也可以自己主动设置打断,为了防止sleep一直等待。}}
监控线程和停止监控线程是两个线程,所以一个线程改主内存内stop的值,另一个线程读stop值。这涉及线程的可见性问题,所以stop要用volatile关键字修饰。
