使用CycleBarrier代替CountDownLatch解决阻塞问题

来源:互联网 发布:怎么做淘宝客漏洞赚钱 编辑:程序博客网 时间:2024/05/18 02:49

问题:一个池塘,有很多鸟和很多鱼,鸟每分钟产生一个后代,鱼每30秒钟产生2个后代。鸟每10秒钟要吃掉一条鱼。建一个池塘,初始化一些鱼和鸟,看看什么时候鸟把鱼吃光。


看到http://blog.csdn.net/ldh911/article/details/7346262的文章后,模仿文章上的代码,自己写了一个实现, 但是出现了阻塞问题。 

代码在http://bbs.csdn.net/topics/390627199

最后终于找到阻塞的原因,在该贴的8楼进行了说明。 虽然能解决,但是不科学,因为要用到Thread.sleep()来等待其他线程执行完毕


所以今天又换了一个方法来解决该问题,解决了阻塞的问题。 

解决办法就是将原来的CountDownLatch换成了CyclicBarrier


代码如下:

package rabitmq01.test03;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;/** * 问题:一个池塘,有很多鸟和很多鱼,鸟每分钟产生一个后代,鱼每30秒钟产生2个后代。鸟每10秒钟要吃掉一条鱼。建一个池塘,初始化一些鱼和鸟,看看什么时候鸟把鱼吃光。 * @author zhoufeng */public class FishBird {long time ;long birdNum ;long fishNum ;Object lock = new Object() ;CyclicBarrier barrier  ;public FishBird(long birdNum , long fishNum){this.birdNum = birdNum ;this.fishNum = fishNum ;}public static void main(String[] args) {FishBird bf = new FishBird(5 , 20) ;bf.start(); }public void start(){FishThread ft = new FishThread() ;BirdThread bt = new BirdThread() ;TimeLine tl = new TimeLine() ;//初始化环形屏障,当barrier对象的await方法被调用两次之后,将会执行tl线程barrier = new CyclicBarrier(2, tl) ;ft.start();bt.start();}public void printInfo(){System.out.printf("time[%d]:birdNum[%d] ,fishNum[%d]\n" ,time , birdNum , fishNum);}private class TimeLine implements Runnable {@Overridepublic void run() {//所有子任务都调用了await方法后,将会执行该方法, 然后所有子线程继续执行if(fishNum <= 0){System.exit(-1);   }time += 10 ;}}private class FishThread extends Thread {@Overridepublic void run() {while(true){try {barrier.await() ;//进入睡眠, 等待所有子任务都进入睡眠  然后再继续} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}synchronized (lock) {if(time % 30 == 0){fishNum += fishNum * 2;printInfo();}}}}}private class BirdThread extends Thread{@Overridepublic void run() {while(true){try {barrier.await() ;  //进入睡眠, 等待所有子任务都进入睡眠  然后再继续} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}  synchronized (lock) {if(time % 10 == 0){fishNum = fishNum >= birdNum ? fishNum - birdNum : 0 ;  if(time % 60 == 0){birdNum += birdNum ;}printInfo();}}}}}}



使用CountDownLatch的一个难题就是如何在调用countDown()方法之前先阻塞本线程。 因为要确保在本线程阻塞之后,主线程再继续

CountDownLatch 与 CycleBarrier 的功能有些相似, 都需要等到规定数量的通知之后,才会被唤醒。 

但是使用CycleBarrier的await()方法时,它会先将本线程阻塞

原创粉丝点击