ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

多线程设计模式——二十二、Latch设计模式

2021-02-26 15:31:40  阅读:231  来源: 互联网

标签:count Latch 设计模式 t5 多线程 线程 阻塞状态 main wait


Latch(阀门)设计模式也叫做 Count Down 设计模式。当若干个线程并发执行完某个特 定的任务,然后等到所有的子任务都执行结束之后再统一汇总。

CountDownLatch 能够使一个线程在等待另外一些线程完成各自工作之后,再继续执 行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后, 计数器的值就会减一。当计数器的值为 0 时,表示所有的线程都已经完成了任务,然后在 CountDownLatch 上等待的线程就可以恢复执行任务。示例代码如下:

代码1:封装自己的CountDownLatch

package com.bjsxt.chapter22;


public class CustomCountDownLatch {
    private volatile int count;
    public CustomCountDownLatch(int count){
        this.count=count;
    }
    public void countDown(){
        synchronized (this){
            this.count--;
            System.out.println(Thread.currentThread().getName()+" will end.");
            this.notifyAll();// 只会唤醒 main线程
        }
    }
    public void await(){
        synchronized (this){
            try{
                while(count!=0){
                    System.out.println(Thread.currentThread().getName()+" will wait.");// 被唤醒了5次
                    this.wait();
                    System.out.println(Thread.currentThread().getName()+" will go on.");
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

代码2:外部调用的测试类

package com.bjsxt.chapter22;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        // main ,t1,t2,...t5 6个线程共享资源 count,countDoenLatch
        int count=5;
        final CustomCountDownLatch countDownLatch=new CustomCountDownLatch(count);
        for(int i=1;i<=count;i++){
            new Thread(()->{
                try {
                    // 它没有占用锁资源
                    TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(30));// 模拟线程执行时间 0~9 s
                    // t1,t2,...,t5 线程执行完毕后countDownLatch.count数量减一
                    // countDown 占用锁资源 countDownLatch
                    countDownLatch.countDown();
                }catch (Exception e){
                    e.printStackTrace();
                }
            },"t"+i).start();
        }
        // main 线程查询countDownLatch.count 为 0 就启动,不为 0 就进入wait队列的阻塞状态,等待被唤醒
        countDownLatch.await();
        // do sth
        System.out.println("元宵节快乐吖");
    }
}

运行结果:
在这里插入图片描述
分析:
开始的时候写的是if语句,不是while循环。一个线程执行完毕后,main线程就会输出结果。如下图。改成while循环就好了。
根本原因是t1,至t5处于线程普通的阻塞状态,过几秒进入Runnable状态。只有main线程处于wait队列的阻塞状态,被其他线程notify后会进入锁池,只有他会竞争CountDownLatch锁,竞争上就进入Runnable状态。

public void await(){
        synchronized (this){
            try{
            if(count!=0)
                    System.out.println(Thread.currentThread().getName()+" will wait.");// 被唤醒了5次
                    this.wait();
                    System.out.println(Thread.currentThread().getName()+" will go on.");
              }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

结果
在这里插入图片描述

查看这六个线程某一时间的jstack,验证分析的是否符合实际:t1至t5的阻塞状态只能是普通的阻塞状态。main是wait队列的阻塞状态。
2021-02-26 14:46:20
main
在这里插入图片描述
t1,至t5
t2线程处于Terminated状态,其他线程陷入普通的阻塞状态。
在这里插入图片描述
2021-02-26 14:46:22:
main:处于wait队列的阻塞状态
在这里插入图片描述

t1至t5
t2,t4处于Terminated状态,其他县城处于普通的阻塞状态。
在这里插入图片描述
2021-02-26 14:46:29:
main:处于wait队列的阻塞状态
在这里插入图片描述
t1至t5:
t2,t4,t5依次进入了Terminated状态;其他县城处于普通的阻塞状态。
在这里插入图片描述
2021-02-26 14:46:33:
main:处于wait队列的阻塞状态
在这里插入图片描述
t1至t5:
t2,t4,t5,t1依次进入了Terminated状态;t3处于普通的阻塞状态
在这里插入图片描述
控制台的输出信息:导致输出2,4,5,1,3顺序结束。每次进入countDown方法,执行notifyAll,实际上只会唤醒main线程,所以会输出5次
main will wait和mainwill go on
在这里插入图片描述

标签:count,Latch,设计模式,t5,多线程,线程,阻塞状态,main,wait
来源: https://blog.csdn.net/qq_32097903/article/details/114132657

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有