精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2010-04-30
CountDownLatch : 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
CountDownLatch 很适合用来将一个任务分为n个独立的部分,等这些部分都完成后继续接下来的任务,CountDownLatch 只能出发一次,计数值不能被重置。 CyclicBarrier: 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。 CyclicBarrier可以多次重复使用
下面是两个例子,一个为基于CountDownLatch 的模拟项目,一个项目可以分为多个模块,只有但这些模块都完成后才可以继续下一步的工作。 一个为基于CyclicBarrier的接力赛模拟,有四个队员,当跑完后报出最终成绩。
package com.woxiaoe.study.thread; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 模拟项目的开发,只有当每个模块都完成后,项目才完成 * 每个模块的用时不同 * @author 小e * * 2010-4-30 下午07:41:37 */ class Module implements Runnable{ private CountDownLatch latch; private String moduleName; private int time;//用时 public Module(CountDownLatch latch, String moduleName,int time) { super(); this.latch = latch; this.moduleName = moduleName; this.time = time; } @Override public void run() { try { work(); latch.countDown(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void work() throws InterruptedException{ TimeUnit.MILLISECONDS.sleep(time); System.out.println(moduleName + " 完成,耗时:" + time); } } class Controller implements Runnable{ private CountDownLatch latch; public Controller(CountDownLatch latch) { super(); this.latch = latch; } @Override public void run() { try { latch.await(); System.out.println("所有模块都完成,任务完成"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public class Project { static final int SIZE = 20; public static void main(String[] args) { CountDownLatch latch = new CountDownLatch(SIZE); Random r = new Random(); ExecutorService exec = Executors.newCachedThreadPool(); Controller controller = new Controller(latch); exec.execute(controller); for(int i = 0; i < SIZE; i++){ exec.execute(new Module(latch, "模块" + (i + 1), r.nextInt(2000))); } exec.shutdown(); } }
Output: 模块4 完成,耗时:108 模块10 完成,耗时:123 模块7 完成,耗时:136 模块19 完成,耗时:235 模块5 完成,耗时:475 模块11 完成,耗时:653 模块1 完成,耗时:745 模块2 完成,耗时:826 模块20 完成,耗时:1030 模块16 完成,耗时:1151 模块3 完成,耗时:1204 模块15 完成,耗时:1219 模块13 完成,耗时:1274 模块17 完成,耗时:1337 模块8 完成,耗时:1366 模块6 完成,耗时:1491 模块14 完成,耗时:1739 模块18 完成,耗时:1766 模块12 完成,耗时:1883 模块9 完成,耗时:1951 所有模块都完成,任务完成 package com.woxiaoe.study.thread; import java.util.Random; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 用java模拟4X100接力赛 * 当结束后 报成绩,应用CyclicBarrier * @author 小e * * 2010-4-30 下午08:13:40 */ class Player implements Runnable{ private String name; private CyclicBarrier barrier; private Player next;//下一棒 private int time;//用时 private boolean run;//第一棒 public Player(String name, CyclicBarrier barrier, boolean run) { super(); this.name = name; this.barrier = barrier; this.run = run; } @Override public void run() { try { synchronized (this) { while(!run){//等待队员 wait(); } } Random r = new Random(); TimeUnit.MILLISECONDS.sleep(r.nextInt(2000)); next(next,11 + r.nextInt(2)); } catch (InterruptedException e) { e.printStackTrace(); } } private void next(Player next, int time) { System.out.println(name + " 用时:" + time + ",交接棒"); if(next != null){ next.setTime(this.time + time); synchronized (next) { next.setRun(true); next.notify(); } }else{ System.out.println("跑完,总用时:" + (this.time + time)); } } public void setTime(int time) { this.time = time; } public int getTime(){ return this.time; } public void setNext(Player next) { this.next = next; } public void setRun(boolean run) { this.run = run; } } public class RelayRace { public static void main(String[] args) throws InterruptedException { final Player[] players = new Player[4]; ExecutorService exec = Executors.newCachedThreadPool(); CyclicBarrier barrier = new CyclicBarrier(4, new Runnable() { @Override public void run() { System.out.println("结束,总用时:" + players[3].getTime()); } }); for(int i = 0; i < 4; i++){ players[i] = new Player("队员" + ( i + 1), barrier, i == 0); } for(int i = 0; i < 4; i++){ if( i < 3){ players[i].setNext(players[i + 1]); exec.execute(players[i]); }else{ exec.execute(players[3]); break; } } /*TimeUnit.SECONDS.sleep(3); * CyclicBarrier 可以重用 for(int i = 0; i < 4; i++){ if( i < 3){ players[i].setNext(players[i + 1]); exec.execute(players[i]); }else{ exec.execute(players[3]); break; } }*/ } } Output:
队员1 用时:11,交接棒
队员2 用时:11,交接棒
队员3 用时:11,交接棒
队员4 用时:12,交接棒
跑完,总用时:45
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-07-14
最后修改:2010-07-14
说白了
CountDownLatch: 一个或者是一部分线程 ,等待另外一部线程都完成了,再继续执行 CyclicBarrier: 所有线程互相等待完成。 我觉得楼主的CyclicBarrier的例子不太好,如果目的是讲CyclicBarrier的话,不如讲4个人一起跑,等4个人都跑到终点了,才可以去吃饭…… package com.wl.test.concurrent.cyclicbarrier; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * * @author HardPass * */ public class CyclicBarrierTest_RelayRace { public static void main(String[] args) throws InterruptedException { ExecutorService exec = Executors.newCachedThreadPool(); final CyclicBarrier barrier = new CyclicBarrier(4, new Runnable() { @Override public void run() { System.out.println("好了,大家可以去吃饭了……" ); } }); System.out.println("要吃饭,必须所有人都到终点,oK?"); System.out.println("不放弃不抛弃!"); for (int i = 0; i < 4; i++) { exec.execute(new Runnable() { @Override public void run() { System.out .println(Thread.currentThread().getName() + ":Go"); try { Thread.sleep((long) (2000 * Math.random())); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":我到终点了"); try { barrier.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (BrokenBarrierException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":终于可以吃饭啦!"); } }); } exec.shutdown(); } } |
|
返回顶楼 | |
发表时间:2010-10-30
CyclicBarrier你传进去根本没用啊
|
|
返回顶楼 | |
发表时间:2011-03-29
yiyidog125 写道 CyclicBarrier你传进去根本没用啊
对啊! 既然你用了concurrent包,为什么还要调用wait()? |
|
返回顶楼 | |
发表时间:2011-03-29
jiefei_download 写道 yiyidog125 写道 CyclicBarrier你传进去根本没用啊
对啊! 既然你用了concurrent包,为什么还要调用wait()? 此贴还被投了“良好贴”? |
|
返回顶楼 | |
浏览 26048 次