突发奇想:实现8个运动员分别热身准备到听到发令枪统一起跑,最终通过随机时间分别到达终点
分析:当所有运动员热身完毕准备就绪后,裁判才能开枪,裁判开枪后所有运动员统一出发,最后经过不同的时间到达了终点
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class TestCountDownLatch {
static AtomicInteger complatePlayers = new AtomicInteger(0);
static AtomicBoolean isPong = new AtomicBoolean(false);
static AtomicInteger mingci = new AtomicInteger(1);
//实现8个运动员分别热身准备到听到发令枪统一起跑
public static void main(String[] args) {
CountDownLatch playerLatch = new CountDownLatch(8);
CountDownLatch caipanLatch = new CountDownLatch(1);
ThreadPoolExecutor pool = new ThreadPoolExecutor(9, 9, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5));
for (int i = 0; i < 8; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(new Random().nextInt(4000)+1000);
System.out.println("运动员"+Thread.currentThread().getName()+"准备就绪");
complatePlayers.incrementAndGet();
playerLatch.countDown();
for(;;){
if(isPong.get()){//裁判开枪了
System.out.println("运动员"+Thread.currentThread().getName()+"出发了!");
int result = new Random().nextInt(9500)+1000;
Thread.sleep(result);
System.out.println("运动员"+Thread.currentThread().getName()+"到达终点!第"+mingci.getAndIncrement()+"名,用时:"+result);
break;
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
pool.execute(runnable);
}
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
while(complatePlayers.get() != 8){
//System.out.println("有人没准备好,1秒后在看看!");
Thread.sleep(1000);
}
System.out.println("8位运动员都准备好了,随时可以发枪!");
Thread.sleep(2000);
isPong.compareAndSet(false, true);
System.out.println("砰!裁判发枪了");
caipanLatch.countDown();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
pool.execute(runnable);
try {
playerLatch.await();
caipanLatch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
首先通过for循环创建8个线程代表8个运动员,使用线程池统一执行,由于需要统一出发,所以肯定需要JUC包下的CountDownLatch或栅栏实现。
裁判发令在另一个线程中,运动员想知道裁判开枪,就需要一个线程可见的变量(裁判想要知道所有运动员都准备好了也是同样的道理),因为volital变量在多线程下不能保证原子性,所以采用了原子类变量。