一个有趣的CountDownLatch实践

突发奇想:实现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变量在多线程下不能保证原子性,所以采用了原子类变量。

你可能感兴趣的:(Java面试笔试)