两阶段终止模式

两阶段终止模式

在并发时,如何让一个线程T1优雅地终止线程T2,优雅指的是给T2一个料理后事的机会。

方法1——利用interrupt

@Slf4j(topic = "c.two")
public class MyTwoInterrupt_ByInterrupt {
    public static void main(String[] args) throws InterruptedException {
        TwoInterruptTermination termination = new TwoInterruptTermination();
        termination.start();

        Thread.sleep(3500);
        termination.stop();
    }
}

@Slf4j(topic = "c.two")
class TwoInterruptTermination {
    private Thread thread;

    public void start() {
        thread = new Thread(() -> {
            while (true) {
                log.debug("执行监控");
                Thread currentThread = Thread.currentThread();
                if (currentThread.isInterrupted()) {
                    log.debug("料理后事");
                    break;
                } else {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        currentThread.interrupt();    //让程序有料理后事的过程,优雅
                    }
                }
            }
        });

        thread.start();
    }

    public void stop() {
        thread.interrupt();
    }
}

方法2——park配合inturrupt

  • park配合inturrupt使用,优雅的暂停、继续线程
  • park只能打断一次:park进程通过inturrupt继续运行之后,打断标志为true,无法继续打断
  • 通过interrupted方法设置打断标志为false,才能继续调用park方法,打断
方法 作用域 作用
interrupted() static 判断当前线程是否被打断,清除打断标记——设置打断标记为false
park() LockSupport 线程暂停,让出cpu
interrupt() 非static 打断线程
private static void main(String[] args) throws Exception{
    Thread t = new Thread(()->{
        log.debug("暂停之前");
        LockSupport.park();
        log.debug("打断状态:{}", Thread.isInterrupt());
    });
    
    t.start();
    
    try {Thread.sleep(1000);} catch(Exception e) {}
    t.interrupt();
}

运行结果:

暂停之前
(等待一秒)
打断状态:true

问题:如果打断标记已经是 true, 再次 park 会失效

解决方法:可以使用 Thread.interrupted() 清除打断状态

private static void main(String[] args) throws Exception{
    Thread t = new Thread(()->{
        for(int i=0; i<4; i++) {
            log.debug("parking");
        	LockSupport.park();
        	+log.debug("打断状态:{}", Thread.interrupted());
        }
    });
    
    t.start();
    
    try {Thread.sleep(1000);} catch(Exception e) {}
    t.interrupt();
}

结果:

暂停之前
打断状态:true
    
暂停之前
打断状态:true
    
暂停之前
打断状态:true
    
暂停之前
打断状态:true
posted @ 2022-04-14 14:03  言思宁  阅读(55)  评论(0编辑  收藏  举报