使用counDownLatch

1.CountDownLatch和CyclicBarrier的相似处和不同处:

CountDownLatch是通过一个计数器来实现的,当我们在new 一个CountDownLatch对象的时候需要带入该计数器值,该值就表示了线程的数量。每当一个线程完成自己的任务后,计数器的值就会减1。当计数器的值变为0时,就表示所有的线程均已经完成了任务,然后就可以恢复等待的线程继续执行了。

虽然,CountDownlatch与CyclicBarrier有那么点相似,但是他们还是存在一些区别的:

CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待

CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。


CountDownLatch最关键的一个参数就是count。

CountDownLatch的几个核心方法:

  await()方法 //countDownLatch的await()方法会使当前线程在锁存器倒计数至零之前,一直等待,除非线程被中断。

  countDown()方法  // countDown()方法可以递减锁存器的计数,如果计数到达零,则释放所有等待的线程。

总结起来,就是CountDownLatch有三个核心部分:

            p1.是 count  计数器

    p2.是 await()方法,使当前线程阻塞,直到count的值为0。

    p3.是 countDown()方法,使计数器器的值减一。

应用场景是这样的:

线程A的运行需要同时拥有N个资源,而这N个资源却被n1,n2,n3, ......,nn个线程分别占有者。

所以:A要想运行的话,它就必须等待n1,n2,n3,......,nn这n个线程都把各自占有的资源释放了才行。

其实,它就是一把 共享资源锁。


2.用一段故事说明一下

相当于现在有一个保险柜,这个保险柜上有三把锁,只有把这三把锁都打开才能打开保险柜 。而这三把锁却被分别交给了三个管理员A,B,C手中。所以,如果我们想打开这个保险柜的话,就必须集齐所有的三把锁。

有一天老板来视察工作,想看下保险柜的钱少了,没有,就找来经理。让经理开门,经理说,你等一下,我打三个电话,把人叫齐了才能把门打开。你现在必须先等一下。于是,经理叫开始逐个打电话,他先打给A,"赶快带上钥匙来公司一趟,老板在等着你",1分钟后,A来了,带来了一把钥匙。然后,经理继续给B打电话,"兄弟,赶快来公司一趟,把钥匙带上,老板要检查保险柜"。2分钟后,B来了。最后,经理又给C打了一个电话,"你他娘的,带上钥匙赶快来公司。" 5分钟后,C也来了,就这样。老板在等候了8分钟后终于集齐了三把钥匙,打开了保险柜,看到了自己的小金库。经过漫长而艰辛的等待他欣慰地漏出了笑容。



3.demo案例

需求:

过来一个请求,这个请求传递过来一个集合,要求我们分别算出该集合元素的总和、积、所有偶数值,并存入库中,然后把处理结果返回客户端。


3.1 创建三个负责和、积、偶数值的Runnable

public class AddRunnable implements Runnable {

private  CountDownLatch  countDown;

private  List  dataList;

public AddRunnable(CountDownLatch countDown,List dataList) {

super();

this.countDown = countDown;

this.dataList = dataList;

}

@Override

public void run() {

Thread.currentThread().setName("sum线程");

//计算和

Long sum=0l;

for (Integer value : dataList) {

sum=sum+value;

}

//计算出来总和后,把结果存库

System.out.println("计算结果是:"+sum+"  把计算结果存库!");

countDown.countDown();//释放锁

System.out.println(Thread.currentThread().getName()+"释放了一把共享锁");

}

}



乘积:

public class MultiRunnable implements Runnable {

private  CountDownLatch  countDown;

private  List  dataList;

public MultiRunnable(CountDownLatch countDown, List dataList) {

super();

this.countDown = countDown;

this.dataList = dataList;

}

@Override

public void run() {

// TODO Auto-generated method stub

Thread.currentThread().setName("muti线程");

//计算和

Long muti=1l;

for (Integer value : dataList) {

muti=muti*value;

System.out.println(muti);

}

//计算出来总和后,把结果存库

System.out.println("乘积结果是:"+muti+"  把乘积结果存库!");

countDown.countDown();//释放锁

System.out.println(Thread.currentThread().getName()+"释放了一把共享锁");

}

}


所有偶数值:

public class OddRunnable implements Runnable {

    private  CountDownLatch  countDown;

private  List  dataList;

public OddRunnable(CountDownLatch countDown, List dataList) {

super();

this.countDown = countDown;

this.dataList = dataList;

}

@Override

public void run() {

// TODO Auto-generated method stub

// TODO Auto-generated method stub

Thread.currentThread().setName("odd线程");

List oddList=new ArrayList();

// 计算和

for (Integer value : dataList) {

if(value%2==0) {

oddList.add(value);

}

}

// 计算出来总和后,把结果存库

System.out.println("求偶结果是:" + oddList.size() + "  把求偶结果存库!");

countDown.countDown();// 释放锁

System.out.println(Thread.currentThread().getName() + "释放了一把共享锁");

}

}




测试:

/**

* 需求:

*    过来一个请求,这个请求传递过来一个集合,要求我们分别算出该集合元素的总和、积、所有偶数值,并存入库中,然后把处理结果返回客户端。

* @author chihaojie

*

*/

public class CountDownLatchTest {

private static  CountDownLatch  countDown;

public static void main(String[] args) {

//只有在其他三个子运算全部完成时,当前线程才能继续

//ExecutorService executorService = Executors.newFixedThreadPool(3);

List  dataList=new ArrayList();

        for (int i = 0; i < 10; i++) {

        dataList.add(i+1);

}

        System.out.println(dataList);

      //处理

        countDown=new CountDownLatch(3);

        //开启三个线程

        new Thread(new AddRunnable(countDown,  dataList)).start();;

        new Thread(new MultiRunnable(countDown, dataList)).start();;

        new Thread(new OddRunnable(countDown, dataList)).start();;

        //执行

        try {

countDown.await();

System.out.println("所有的线程都运算完了");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}




运行结果

你可能感兴趣的:(使用counDownLatch)