【多线程_并发工具】 闭锁-CountDownLacth

来源:互联网 发布:塞规设计软件 编辑:程序博客网 时间:2024/05/20 06:30

主要的例子,参考自博客:http://blog.csdn.net/lmj623565791/article/details/26626391。


先看一个问题:

每天起早贪黑的上班,父母每天也要上班,话说今天定了个饭店,一家人一起吃个饭,通知大家下班去饭店集合。假设:3个人在不同的地方上班,必须等到3个人到场才能吃饭,用程序如何实现呢?

不正确的实现1.

    package com.zhy.concurrency.latch;            public class Test1      {          /**          * 模拟爸爸去饭店          */          public static void fatherToRes()          {              System.out.println("爸爸步行去饭店需要3小时。");          }                /**          * 模拟我去饭店          */          public static void motherToRes()          {              System.out.println("妈妈挤公交去饭店需要2小时。");          }                /**          * 模拟妈妈去饭店          */          public static void meToRes()          {              System.out.println("我乘地铁去饭店需要1小时。");          }                /**          * 模拟一家人到齐了          */          public static void togetherToEat()          {              System.out.println("一家人到齐了,开始吃饭");          }                public static void main(String[] args)          {              fatherToRes();              motherToRes();              meToRes();              togetherToEat();          }      }  

输出结果:

    爸爸步行去饭店需要3小时。      妈妈挤公交去饭店需要2小时。      我乘地铁去饭店需要1小时。      一家人到齐了,开始吃饭  

所有人的到达应该并行的而不是穿行的,所以需要并发。


不正确的实现2:

    public static void main(String[] args)          {              new Thread()              {                  public void run()                  {                      fatherToRes();                  };              }.start();              new Thread()              {                  public void run()                  {                      motherToRes();                  };              }.start();              new Thread()              {                  public void run()                  {                      meToRes();                  };              }.start();                            togetherToEat();          }  

输出结果:

    一家人到齐了,开始吃饭      我乘地铁去饭店需要1小时。      妈妈挤公交去饭店需要2小时。      爸爸步行去饭店需要3小时。  

开始吃饭一定要等到所有人到达才行。


正确的实现1.

    private static volatile int i = 3;                public static void main(String[] args)          {                    new Thread()              {                  public void run()                  {                      fatherToRes();                      i--;                  };              }.start();              new Thread()              {                  public void run()                  {                      motherToRes();                      i--;                  };              }.start();              new Thread()              {                  public void run()                  {                      meToRes();                      i--;                  };              }.start();                    while (i != 0);              togetherToEat();          }  
这样做对CPU的负荷大。


正确的实现2:

public class demo {public static CountDownLatch latch = new CountDownLatch(3);public static void fatherGoRes(){System.out.println("父亲到需要三个小时");}public static void motherGoRes(){System.out.println("母亲到达需要2个小时");}public static void sonGoRes(){System.out.println("儿子到达需要1个小时");}public static void togetherToEat(){System.out.println("人都到期了,准备吃饭。");}/** * @param args */public static void main(String[] args) {// TODO Auto-generated meth奥od stubnew Thread(new Runnable() {public void run() {// TODO Auto-generated method stubfatherGoRes();//递减锁存器的计数,如果计数到达零,则释放所有等待的线程latch.countDown();}}).start();new Thread(new Runnable() {public void run() {motherGoRes();latch.countDown();}}).start();new Thread(new Runnable() {public void run() {sonGoRes();//递减锁存器的计数,如果计数到达零,则释放所有等待的线程latch.countDown();}}).start();//使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断try {latch.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}togetherToEat();}}


所以什么是闭锁呢?

《Java 并发编程实践》中解释道:闭锁的作用类似于一扇门:在闭锁到达结束状态之前,这扇门一直是关闭着的,不允许任何线程通过,当到达结束状态时,这扇门会打开并允许所有的线程通过。且当门打开了,就永远保持打开状态。


他的使用场景:

1.确保某个计算在其需要的所有资源都被初始化之后才继续执行

2.确保某个服务再其依赖的所有其他服务都已经启动后才启动。

3.等待某个操作的所有参入这都要就绪在继续执行。


CountDownLatch的主要方法如下:

 void await()           使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。  boolean await(long timeout, TimeUnit unit)           使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。  void countDown()           递减锁存器的计数,如果计数到达零,则释放所有等待的线程。  long getCount()           返回当前计数。  String toString()           返回标识此锁存器及其状态的字符串。 


0 0
原创粉丝点击