设计模式——终止模式之两阶段终止模式

Two Phase Termination
在一个线程 T1 中如何“优雅”终止线程 T2?这里的【优雅】指的是给 T2 一个料理后事的机会。

1. 错误思路

  • 使用线程对象的 stop() 方法停止线程
    stop 方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀死后就再也没有机会释放锁,
    其它线程将永远无法获取锁
  • 使用 System.exit(int) 方法停止线程
    目的仅是停止一个线程,但这种做法会让整个程序都停止

2. 两阶段终止模式

在这里插入图片描述

2.1 利用 isInterrupted

interrupt 可以打断正在执行的线程,无论这个线程是在 sleep,wait,还是正常运行

package cn.itcast.test;

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();
        tpt.start();
        tpt.start();

        /*Thread.sleep(3500);
        log.debug("停止监控");
        tpt.stop();*/
    }
}

@Slf4j(topic = "c.TwoPhaseTermination")
class TwoPhaseTermination {
    // 监控线程
    private Thread monitorThread;
    // 停止标记
    private volatile boolean stop = false;
    // 判断是否执行过 start 方法
    private boolean starting = false;

    // 启动监控线程
    public void start() {
        synchronized (this) {
            if (starting) { // false
                return;
            }
            starting = true;
        }
        monitorThread = new Thread(() -> {
            while (true) {
                Thread current = Thread.currentThread();
                // 是否被打断
                if (stop) {
                    log.debug("料理后事");
                    break;
                }
                try {
                    Thread.sleep(1000);
                    log.debug("执行监控记录");
                } catch (InterruptedException e) {
                }
            }
        }, "monitor");
        monitorThread.start();
    }

    // 停止监控线程
    public void stop() {
        stop = true;
        monitorThread.interrupt();
    }
}

调用

TPTInterrupt t = new TPTInterrupt();
t.start();
Thread.sleep(3500);
log.debug("stop");
t.stop();

2.2 利用停止标记

// 停止标记用 volatile 是为了保证该变量在多个线程之间的可见性
// 我们的例子中,即主线程把它修改为 true 对 t1 线程可见
class TPTVolatile {
 private Thread thread;
 private volatile boolean stop = false;
 public void start(){
 thread = new Thread(() -> {
 while(true) {
 Thread current = Thread.currentThread();
 if(stop) {
 log.debug("料理后事");
 break;
 }
 try {
 Thread.sleep(1000);
 log.debug("将结果保存");
 } catch (InterruptedException e) {
 }
 // 执行监控操作
 }
 },"监控线程");
 thread.start();
 }
 public void stop() {
 stop = true;
 thread.interrupt();
 }
}

interrupt-打断park

package cn.itcast.test;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.LockSupport;

import static cn.itcast.n2.util.Sleeper.sleep;

@Slf4j(topic = "c.Test14")
public class Test14 {

    private static void test4() {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                log.debug("park...");
                LockSupport.park();
                log.debug("打断状态:{}", Thread.interrupted());   //  interrupted 返回标记后会把打断状态清空,park就可以再次使用了

                LockSupport.park();   //Thread.currentThread().isInterrupted()不会清空给打断状态,true会使park失效
                log.debug("2park...");


            }
        });
        t1.start();


        sleep(1);
        t1.interrupt();
    }

    private static void test3() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.debug("park...");
            LockSupport.park();
            log.debug("unpark...");
            log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
        }, "t1");
        t1.start();

        sleep(1);
        t1.interrupt();

    }

    public static void main(String[] args) throws InterruptedException {
        test3();
    }
}

相关推荐

  1. 设计模式模板模式

    2024-04-27 15:38:03       21 阅读
  2. 【前端设计模式模版方法模式

    2024-04-27 15:38:03       61 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-27 15:38:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-27 15:38:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-27 15:38:03       87 阅读
  4. Python语言-面向对象

    2024-04-27 15:38:03       96 阅读

热门阅读

  1. 《设计模式之美》第五章 总结

    2024-04-27 15:38:03       37 阅读
  2. 动手学深度学习——pandas

    2024-04-27 15:38:03       29 阅读
  3. c++11 call_once 和 once_flag

    2024-04-27 15:38:03       26 阅读
  4. vue项目,普通js文件添加全局变量

    2024-04-27 15:38:03       28 阅读
  5. STM32 ULINK

    2024-04-27 15:38:03       30 阅读
  6. 2023年第13届山东省大学生程序设计竞赛题解

    2024-04-27 15:38:03       28 阅读
  7. Linux中的时间戳mtime,ctime,ctime

    2024-04-27 15:38:03       30 阅读
  8. 等保测评试题分享(7)

    2024-04-27 15:38:03       37 阅读
  9. TS泛型类型

    2024-04-27 15:38:03       36 阅读
  10. MySQL 数据表

    2024-04-27 15:38:03       30 阅读