之前从网上看到一段代码,关于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);
}
}