【JUC并发】黑马程序员:终止模式之线程优雅打断,interrupt版、打断标记+volatile版

场景介绍

设计一个单例的监控类,实现 开启 和 停止 功能。

interrupt版

实现

/**
 * 监控类:创建成员线程变量,执行监控任务。提供 开启 和 停止 功能。
 */
@Slf4j(topic = "c.five-Demo1")
final class TPTInterrupt{
	//1.单例模式固定套路。详细单例模式介绍参考文章《单例模式正确姿势汇总——普通饿汉式,枚举饿汉式,普通懒汉式,DCL懒汉式,静态内部类懒汉式》
    private static volatile TPTInterrupt tptInterrupt;
    //线程名字
    private final String name;
    private TPTVolatile(){}
    private TPTInterrupt(String value){
        name=value;
    }
    //2.创建监控类具体任务执行线程
    private final Thread thread=new Thread(()->{
        Thread current=Thread.currentThread();
        while(true){
        	//2.1 判断是否调用 停止 方法。
            if(current.isInterrupted()){
                log.debug("被打断-料理后事");
                break;
            }
            log.debug("执行监控任务");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                log.debug("睡眠时(模拟执行监控任务)被打断");
                current.interrupt();
            }
        }
    },"TPT");
    //开启监控
    public final void startTPT(){
        try{
            thread.start();
        }catch (IllegalThreadStateException e){
            System.out.println("监控进程无法被多次调用");
        }
    }
    //停止监控
    public final void stopTPT(){
    	//调用线程的打断方法
        thread.interrupt();
    }
    //获取监控对象:单例模式固定套路
    public static TPTInterrupt getTPTInterrupt(){
        if(tptInterrupt!=null){
            return tptInterrupt;
        }else {
            synchronized (TPTInterrupt.class){
                if(tptInterrupt!=null){
                    return tptInterrupt;
                }
                tptInterrupt=new TPTInterrupt("后台监控线程");
                return tptInterrupt;
            }
        }
    }
}

测试

public static void main(String[] args) throws InterruptedException {
        //interrupt版
        TPTInterrupt tptInterrupt = TPTInterrupt.getTPTInterrupt();
        tptInterrupt.startTPT();
        tptInterrupt.startTPT();
        TimeUnit.SECONDS.sleep(2);
        tptInterrupt.stopTPT();

    }

效果

监控进程无法被多次调用
00:19:16 [TPT] c.five-Demo1 - 执行监控任务
00:19:17 [TPT] c.five-Demo1 - 执行监控任务
00:19:18 [TPT] c.five-Demo1 - 睡眠时(模拟执行监控任务)被打断
00:19:18 [TPT] c.five-Demo1 - 被打断-料理后事

打断标记+volatile版

实现

/**
 * 监控类:创建成员线程变量,执行监控任务。提供 开启 和 停止 功能。
 */
@Slf4j(topic = "c.five-Demo1")
final class TPTVolatile{
	//1.单例模式固定套路。详细单例模式介绍参考文章《单例模式正确姿势汇总——普通饿汉式,枚举饿汉式,普通懒汉式,DCL懒汉式,静态内部类懒汉式》
    private static volatile TPTVolatile tptVolatile;
    //2.打断标记。volatile 修饰:保证可见性,有序性
    private static volatile boolean interrupted=false;
    //3.线程名字
    private final String name;
    private TPTVolatile(){

    }
    private TPTVolatile(String name){
        this.name=name;
    }
    //4.创建监控类具体任务执行线程
    private final static Thread thread=new Thread(()->{
		//4.1 循环执行监控任务
        while(true){
        	//4.2 判断监控任务是否需要停止
            if(interrupted){
                log.debug("被打断-料理后事");
                break;
            }
            log.debug("执行监控任务");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                log.debug("睡眠时(模拟执行监控任务)被打断");
                interrupted=true;
            }
        }
    },"TPT");
    //开启监控线程
    public final void startTPT(){
        try{
            thread.start();
        }catch (IllegalThreadStateException e){
            System.out.println("监控进程无法被多次调用");
        }
    }
    //停止监控(打断监控线程)
    public final void stopTPT(){
        interrupted=true;
    }
    //获得监控对象
    public static TPTVolatile getTPTVolatile(){
        if(tptVolatile!=null){
            return tptVolatile;
        }else {
            synchronized (TPTVolatile.class){
                if(tptVolatile!=null){
                    return tptVolatile;
                }
                tptVolatile=new TPTVolatile("后台监控线程");
                return tptVolatile;
            }
        }
    }
}

测试

public static void main(String[] args) throws InterruptedException {
        //打断标记+volatile版
        TPTVolatile tptVolatile=TPTVolatile.getTPTVolatile();
        tptVolatile.startTPT();
        tptVolatile.startTPT();
        TimeUnit.SECONDS.sleep(2);
        tptVolatile.stopTPT();

    }

效果

监控进程无法被多次调用
00:21:07 [TPT] c.five-Demo1 - 执行监控任务
00:21:08 [TPT] c.five-Demo1 - 执行监控任务
00:21:09 [TPT] c.five-Demo1 - 被打断-料理后事
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愿你满腹经纶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值