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

public class Test {
    public static void main(String[] args){
//        ProgrammerTravleTest.test();
        ProgrammerTravleTest.test2();
    }
}

/*
    第23章 Latch 设计模式

    若干线程并发执行某个特定的任务,然后等到所有的子任务都执行结束之后再统一汇总。

    23.2 CountDownLatch程序实现

    23.2.1 无限等待的Latch
 */
class WaitTimeoutException extends Exception{
    public WaitTimeoutException(String msg) {
        super(msg);
    }
}

abstract class Latch{
    protected int limit;

    public Latch(int limit) {
        this.limit = limit;
    }

    //该方法会使得当前线程一致等待
    public abstract void await()throws InterruptedException;

    //带超时功能的
    public abstract void await(TimeUnit unit, long time) throws InterruptedException,WaitTimeoutException;

    //当任务线程完成工作之后调用该方法使得计数器减一
    public abstract void countDown();

    //获取当前还有多少个线程没有完成任务
    public abstract int getUnarrived();
}

//无限等待CountDownLatch实现
class CountDownLatch extends Latch{

    public CountDownLatch(int limit) {
        super(limit);
    }

    @Override
    public void await() throws InterruptedException {
        synchronized (this) {
            while (limit > 0) {
                this.wait();
            }
        }
    }

    /*
        这个写法在写改写sysn时用过了。
     */
    @Override
    public void await(TimeUnit unit, long time) throws InterruptedException, WaitTimeoutException {
        if (time < 0) {
            throw new IllegalArgumentException("The time is invalid.");
        }

        long remainingNanos = unit.toNanos(time);

        final long endNanos = System.nanoTime()+ remainingNanos;
        synchronized (this) {
            while (limit > 0) {
                if (TimeUnit.NANOSECONDS.toMillis(remainingNanos) <= 0) {
                    throw new WaitTimeoutException("The wait time over specify time.");
                }

                this.wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos));
                remainingNanos=endNanos-System.nanoTime();
            }
        }
    }

    @Override
    public void countDown() {
        synchronized (this) {
            if (limit <= 0) {
                throw new IllegalArgumentException("all of task already arrived");
            }
            limit--;
            this.notifyAll();
        }
    }

    @Override
    public int getUnarrived() {
        return limit;
    }
}

//程序测试齐心协力打开门阀
class ProgrammerTravle extends Thread{
    private final Latch latch;
    private final String programmer;
    private final String transportation;

    public ProgrammerTravle(Latch latch, String programmer, String transportation) {
        this.latch = latch;
        this.programmer = programmer;
        this.transportation = transportation;
    }

    @Override
    public void run() {
        System.out.println(programmer+" start take the transportation["+transportation+"]");
        try{
            TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(10));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(programmer+" arrived by "+transportation);
        latch.countDown();
    }
}

class ProgrammerTravleTest{
    public static void test(){
        Latch latch = new CountDownLatch(4);
        new ProgrammerTravle(latch,"A","a").start();
        new ProgrammerTravle(latch,"B","b").start();
        new ProgrammerTravle(latch,"C","c").start();
        new ProgrammerTravle(latch,"D","d").start();

        try {
            latch.await();
            System.out.println("==all of programmer arrived==");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void test2(){
        Latch latch = new CountDownLatch(4);
        new ProgrammerTravle(latch,"A","a").start();
        new ProgrammerTravle(latch,"B","b").start();
        new ProgrammerTravle(latch,"C","c").start();
        new ProgrammerTravle(latch,"D","d").start();

        try {
            latch.await(TimeUnit.SECONDS,5);
            System.out.println("==all of programmer arrived==");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (WaitTimeoutException e) {
            e.printStackTrace();
        }
    }
}

《Java高并发编程详解》笔记

Latch设计模式的更多相关文章

  1. Android开发中常见的设计模式

    对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次.而在android开发中,必要的了解一些设计模式又是非常有必要的.对于想系统的学习设计模式的 ...

  2. Spring源码分析 之浅谈设计模式

    一直想专门写个Spring源码的博客,工作了,可以全身性的投入到互联网行业中.虽然加班很严重,但是依然很开心.趁着凌晨有时间,总结总结. 首先spring,相信大家都很熟悉了. 1.轻量级  零配置, ...

  3. 转 多线程 闭锁(Latch) 栅栏(CyclicBarrier)

    java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier) 标签: java并发编程 2015-05-28 16:45 2939人阅读 评论(0) 收藏 举报 本文章已收录于: . ...

  4. MVVM设计模式和WPF中的实现(四)事件绑定

    MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  5. java EE设计模式简介

    1.何为设计模式 设计模式提供了对常见应用设计问题的解决方案.在面向对象的编程中,设计模式通常在解决与对象创建和交互相关的问题,而非整体软件架构所面对的大规模问题,它们以样板代码的形式提供了通用的解决 ...

  6. 计算机程序的思维逻辑 (54) - 剖析Collections - 设计模式

    上节我们提到,类Collections中大概有两类功能,第一类是对容器接口对象进行操作,第二类是返回一个容器接口对象,上节我们介绍了第一类,本节我们介绍第二类. 第二类方法大概可以分为两组: 接受其他 ...

  7. 《JavaScript设计模式 张》整理

    最近在研读另外一本关于设计模式的书<JavaScript设计模式>,这本书中描述了更多的设计模式. 一.创建型设计模式 包括简单工厂.工厂方法.抽象工厂.建造者.原型和单例模式. 1)简单 ...

  8. 《JavaScript设计模式与开发实践》整理

    最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...

  9. 设计模式之行为类模式大PK

                                        行为类模式大PK 行为类模式包括责任链模式.命令模式.解释器模式.迭代器模式.中介者模式.备忘录模式.观察者模式.状态模式.策略 ...

随机推荐

  1. shell条件测试结构

    条件测试结构 if/then结构用来判断命令列表的退出状态码是否为0(因为在UNIX惯例, 0表示"成功"), 如果成功的话, 那么就执行接下来的一个或多个命令. 有一个专有命令[ ...

  2. .NET解析xml字符串,通过反射给实体类对象赋值,获取实体类数据列表

    /// <summary> /// 解析xml字符串 转换为实体类列表数据 /// </summary> /// <param name="xmlStr&quo ...

  3. 关于 win32 下磁盘的遍历方法

    最近要写个在线专杀的东东,虽然是专杀(本来只要清除几个特定的文件和杀几个特定的进程,然后把用户的注册表恢复正常,很多病毒木马最喜欢干的一件事情就是写 映像劫持 然后机器一重启,安全相关的软件全部玩完了 ...

  4. 管道Demo

    使用管道实现读取DOS命令结果,界面如下: 主要代码如下: UpdateData(TRUE); //创建一个管道,用于接收命令执行结果 SECURITY_ATTRIBUTES sa; ZeroMemo ...

  5. git实战经验(很实用)

    推荐学习git很好的网站https://www.breakyizhan.com/git/216.html 以下内容,虽然编排不行,但是请认真的读下去,都是自己平时请自操作的,放心使用. 这是个人的gi ...

  6. 一文详解 LVS、Nginx 及 HAProxy 工作原理( 附大图 )

    当前大多数的互联网系统都使用了服务器集群技术,集群是将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是 Web 应用服务器集群,也可以是数据库服务器集群,还可以是分布式缓存服务器 ...

  7. 【Linux杂记】screen命令

    screen命令: 解决的问题:有些进程启动后,一旦断开ssh容易断掉,所以新建一个screen(可以理解成窗口)并行运行 守护进程的方式:linux守护进程的方式实现开机启动某些特定的程序 屏幕命令 ...

  8. 【设计模式】行为型06命令模式(Command Pattern)

    命令模式 个人理解:命令模式,本质上是一种多层次的封装. 好处:降低耦合,扩展极其方便. 以下一段文案摘抄自:http://www.runoob.com/design-pattern/command- ...

  9. VIM技巧, .vimrc文件

    将 .vimrc文件上传到用户家目录下 文件内容如下: autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()&quo ...

  10. Linux搭建基于BIND的DNS服务器

    Linux搭建基于BIND的DNS服务器   实验目标: 通过本实验掌握基于Linux的DNS服务器搭建. 实验步骤: 1.安装BIND 2.防火墙放通DNS服务 3.编辑BIND的主配置文件 4.编 ...