用线程模拟,CountDownLatch,CyclicBarrier

来源:互联网 发布:js 范围选择滑块插件 编辑:程序博客网 时间:2024/05/16 06:13

之前从网上看到一段代码,关于wait和notify的,但是发现代码写的有bug,并且程序的逻辑我感觉并不是太清楚,但是程序所举的例子还是很有意义的。


因此我改写了一下,用面向对象的思维。


import java.util.Collection;import java.util.Collections;import java.util.HashSet;import java.util.Set;import java.util.concurrent.atomic.AtomicInteger;/** * 用于模拟在一个game中先让运动员全体准备好,然后一起开始game *  * @author donggua *  */public class Game {public static AtomicInteger readPlayerCount = new AtomicInteger(0);// 运动员的数量private Set<Athlete> players = new HashSet<Athlete>();// 用于存放运动员,表示参与这个game的集合public void addPlayer(Athlete one) {players.add(one);}public void removePlayer(Athlete one) {players.remove(one);}public Collection<Athlete> getPlayers() {return Collections.unmodifiableSet(players);}/** * game的准备阶段,表示通知所有的运动员准备好 */public void prepare() {for (Athlete player : players) {player.ready();}}/** * game开始,通知所有的运动员开始 */public void go() {synchronized (Game.class) {Game.class.notifyAll();}}public static void main(String[] args) {Game game = new Game();for (int i = 0; i < 10; i++) {game.addPlayer(new Athlete(i));}game.prepare();while (true) {if (readPlayerCount.get() == 10) {// 所有的运动员准备好之后,game开始game.go();break;}}}}

/** * 运动员实体类 *  * @author donggua *  */class Athlete implements Runnable {private final int id;public Athlete(int id) {this.id = id;}public String toString() {return "Athlete<" + id + ">";}public void ready() {new Thread(this).start();}public void run() {synchronized (Game.class) {try {Game.readPlayerCount.addAndGet(1);System.out.println(this + " ready!");Game.class.wait();System.out.println(this + "go");} catch (InterruptedException e) {e.printStackTrace();}}}}





上面是用到了synchronized,notifyAll ,wait等java原生的方式实现了这一功能,但是jdk中还是提供了更加面向对象的实现如:CountDownLatch 和CyclicBarrier

下面就用这两个类分别改写上面的程序:


import java.util.concurrent.CountDownLatch;/** * 运动员实体类 *  * @author donggua *  */class AthleteCountDownLatch implements Runnable {private int id;private CountDownLatch startSignal;private CountDownLatch doneSignal;AthleteCountDownLatch(CountDownLatch startSignal, CountDownLatch doneSignal, int id) {this.startSignal = startSignal;this.doneSignal = doneSignal;this.id = id;}public AthleteCountDownLatch(int id) {this.id = id;}public String toString() {return "Athlete<" + id + ">";}public void ready() {new Thread(this).start();}public void run() {try {GameCountLatch.readPlayerCount.addAndGet(1);System.out.println(this.toString() + "ready。。。");startSignal.await();doWork();doneSignal.countDown();} catch (InterruptedException ex) {}}private void doWork() {System.out.println(toString() + "game 进行中。。。。。");}}


import java.util.Collection;import java.util.Collections;import java.util.HashSet;import java.util.Set;import java.util.concurrent.CountDownLatch;import java.util.concurrent.atomic.AtomicInteger;/** * 用于模拟在一个game中先让运动员全体准备好,然后一起开始game *  * @author donggua *  */public class GameCountLatch {public static AtomicInteger readPlayerCount = new AtomicInteger(0);// 运动员的数量private Set<AthleteCountDownLatch> players = new HashSet<AthleteCountDownLatch>();// 用于存放运动员,表示参与这个game的集合public void addPlayer(AthleteCountDownLatch one) {players.add(one);}/** * game的准备阶段,表示通知所有的运动员准备好 */public void prepare(CountDownLatch startSignal, CountDownLatch doneSignal, GameCountLatch game) {for (int i = 0; i < 10; i++) {game.addPlayer(new AthleteCountDownLatch(startSignal, doneSignal, i));}for (AthleteCountDownLatch player : players) {player.ready();}}/** * game开始,通知所有的运动员开始 */public void go(CountDownLatch startSignal) {while (true) {if (readPlayerCount.get() == 10) {// 所有的运动员准备好之后,game开始startSignal.countDown();break;}}}public static void main(String[] args) {CountDownLatch startSignal = new CountDownLatch(1);CountDownLatch endSignal = new CountDownLatch(10);GameCountLatch game = new GameCountLatch();game.prepare(startSignal, endSignal, game);game.go(startSignal);try {endSignal.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("game 结束");}}


可以看到上面的程序比上上个稍微好一点,关键的是能够得到game结束的时机点。


import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;/** * 运动员实体类 *  * @author donggua *  */class AthleteCyclicBarrier implements Runnable {private final int id;private CyclicBarrier barrier;public AthleteCyclicBarrier(CyclicBarrier barrier, int id) {this.barrier = barrier;this.id = id;}public String toString() {return "Athlete<" + id + ">";}public void readyAndGo() {new Thread(this).start();}public void run() {synchronized (barrier) {System.out.println(toString() + " ready!  已经有" + (barrier.getNumberWaiting() + 1) + "个准备好了");}try {barrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}System.out.println(toString() + " gameing ...!");try {barrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}}

import java.util.HashSet;import java.util.Set;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.atomic.AtomicInteger;/** * 用于模拟在一个game中先让运动员全体准备好,然后一起开始game * @author donggua * */public class GameCyclicBarrier {public static AtomicInteger readPlayerCount = new AtomicInteger(0);//运动员的数量private Set<AthleteCyclicBarrier> players = new HashSet<AthleteCyclicBarrier>();//用于存放运动员,表示参与这个game的集合public void addPlayer(AthleteCyclicBarrier one) {players.add(one);}/*** game的准备阶段,表示通知所有的运动员准备好*/public void readyAndGo(CyclicBarrier barrier,GameCyclicBarrier game) {for (int i = 0; i < 10; i++) {game.addPlayer(new AthleteCyclicBarrier(barrier,i));}for(AthleteCyclicBarrier player : players) {player.readyAndGo();}}public static void main(String[] args) {CyclicBarrier cyclicBarrier = new CyclicBarrier(10);GameCyclicBarrier game = new GameCyclicBarrier();game.readyAndGo(cyclicBarrier, game);}}




0 0
原创粉丝点击