importjava.util.ArrayList;importjava.util.List;importjava.util.Random;importjava.util.concurrent.CountDownLatch;importjava.util.concurrent.CyclicBarrier;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;public classCountDownLatchTest {//运动员数量量
private static int SPORTSMAN_COUNT = 10;private static final Random random = newRandom();//用于判断发令之前运动员是否已经进⼊入准备状态,需要等待10个运动员准备就绪,占有锁,等待10个运动员完成,释放锁。
private static CountDownLatch readyLatch = newCountDownLatch(SPORTSMAN_COUNT);//⽤用于判断裁判是否已经发令,占有锁,等待裁判发令完成,释放锁
private static CountDownLatch startLatch = new CountDownLatch(1);//设置终点屏障,⽤用于计算成绩
private static CyclicBarrier cb = new CyclicBarrier(SPORTSMAN_COUNT, newRunnable() {
@Overridepublic voidrun() {
CountDownLatchTest.transcript.sort((Sportsman p1, Sportsman p2)-> p1.getTranscript() -p2.getTranscript());
System.out.println("排名成绩单:" +CountDownLatchTest.transcript);
CountDownLatchTest.transcript.clear();
}
});//成绩单
private static List transcript = new ArrayList(SPORTSMAN_COUNT);public static voidmain(String[] args) {//用于判断发令之前运动员是否已经进⼊准备状态,需要等待10个运动员准备就绪,占有锁,等待10 个运动员完成,释放锁。//CountDownLatch readyLatch = new CountDownLatch(SPORTSMAN_COUNT);//⽤用于判断裁判是否已经发令,占有锁,等待裁判发令完成,释放锁//CountDownLatch startLatch = new CountDownLatch(1);//启动10个线程,也就是10个运动员,做准备⼯工作
for (int i = 0; i < SPORTSMAN_COUNT; i++) {
Thread t= new Thread(new RunTask((i + 1) + "号运动员", readyLatch, startLatch));
t.start();
}//当前运动员在其他运动员准备就绪前⼀一直等待,也就是说等readyLatch倒数计数器器为0之前⼀一直等待
try{
readyLatch.await();
}catch(InterruptedException e) {
e.printStackTrace();
}//裁判发令,释放锁
startLatch.countDown();
System.out.println("裁判:所有运动员准备完毕,开始跑...");
}/**运动员类*/
static classSportsman {privateString name;private inttranscript;public Sportsman(String name, inttranscript) {this.name =name;this.transcript =transcript;
}
@Overridepublic booleanequals(Object obj) {boolean result = false;if (obj instanceofSportsman) {
result= ((Sportsman) obj).getTranscript() == this.transcript;
}returnresult;
}
@OverridepublicString toString() {return this.name + ":" + this.transcript + " ms";
}publicString getName() {returnname;
}public intgetTranscript() {returntranscript;
}
}/**跑任务类*/
static class RunTask implementsRunnable {private Lock lock = newReentrantLock();privateCountDownLatch ready;privateCountDownLatch start;privateString name;/*** (构造⽅方法)
*@paramready
*@paramstart
*@paramname 运动员名称*/
publicRunTask(String name, CountDownLatch ready, CountDownLatch start) {this.ready =ready;this.start =start;this.name =name;
}
@Overridepublic voidrun() {
lock.lock();try{//运动员准备就绪的逻辑,准备readyTime秒
int readyTime = random.nextInt(1000);
System.out.println(name+ ":我需要" + readyTime + "秒的时间准备。");try{
Thread.sleep(readyTime);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+ "我已经准备完毕!");//释放锁readyLatch-1,表示⼀一个运动员已经就绪
ready.countDown();//待裁判发开始命令
try{
start.await();
}catch(InterruptedException e) {
}
System.out.println(name+ ":开跑...");int costTime = random.nextInt(500);try{
Thread.sleep(costTime);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+ ":开跑到达终点。成绩:" + costTime + "ms");
transcript.add(newSportsman(name, costTime));//等待成绩
cb.await();
}catch(Exception e) {
}finally{
lock.unlock();
}
}
}
}