有个例子,比如赛车游戏,有8台车在线外等待,倒计时5秒后才能操作行驶.
这种场景在面试也会有问到,一般问你怎么设计,如果你只懂得线程池,那还不够,如果你说出闭锁的概念;
那恭喜你,你答对了
上个例子
package com.cdg.threads;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 闭锁的例子
* 比如有三个团,每个团必须等待所有团(3个团)到达后才能去下一个点.
* 地点:先到深圳,再到广州,再到重庆.
* @author Cookie.Joo
*
*/
public class CyclicBarrierDemo {
//徒步旅行(耗时),到深圳5个小时,到广州8个小时,到深圳10个小时
private static int[] timeForWalk = { 5, 8, 10 };
//自驾游
private static int[] timeForSelf = { 1, 3, 4 };
//乘坐大巴
private static int[] timeForBus = { 2,4,6 };
//经过地点
private static String[] address = { "深圳","广州","重庆"};
static String nowTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date())+ ": ";
}
static class Tour implements Runnable {
private int[] timeForUse;
private CyclicBarrier barrier;
private String tourName;
public Tour(int[] timeForUse, CyclicBarrier barrier, String tourName) {
this.timeForUse = timeForUse;
this.barrier = barrier;
this.tourName = tourName;
}
@Override
public void run() {
try {
for(int i = 0;i< address.length;i++){
TimeUnit.SECONDS.sleep(timeForUse[i] * 1);
System.out.println(nowTime() + tourName + "\t到达:" + address[i] + "\t耗时:" + timeForUse[i]);
barrier.await();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("各路人马准备出发!");
//三个旅行团都到齐后执行该方法
Runnable run = new Runnable() {
@Override
public void run() {
System.out.println("我们在这里!");
}
};
CyclicBarrier barrier = new CyclicBarrier(3, run);
ExecutorService exec = Executors.newFixedThreadPool(3);
exec.submit(new Tour(timeForWalk, barrier, "步行"));
exec.submit(new Tour(timeForSelf, barrier, "自驾游"));
exec.submit(new Tour(timeForBus, barrier, "坐大巴"));
exec.shutdown();
}
}
运行结果:
各路人马准备出发!
2014-07-07 14:22:32: 自驾游 到达:深圳耗时:1
2014-07-07 14:22:32: 坐大巴 到达:深圳耗时:2
2014-07-07 14:22:35: 步行 到达:深圳耗时:5
我们在这里!
2014-07-07 14:22:38: 自驾游 到达:广州耗时:3
2014-07-07 14:22:39: 坐大巴 到达:广州耗时:4
2014-07-07 14:22:43: 步行 到达:广州耗时:8
我们在这里!
2014-07-07 14:22:47: 自驾游 到达:重庆耗时:4
2014-07-07 14:22:49: 坐大巴 到达:重庆耗时:6
2014-07-07 14:22:53: 步行 到达:重庆耗时:10
我们在这里!
package com.cdg.concurrent;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class CountDownLatchTest {
private static final int N = 5;
public static void main(String[] args) throws InterruptedException {
CountDownLatch startLatch = new CountDownLatch(1);
CountDownLatch endLatch = new CountDownLatch(N);
for (int i = 0; i < N; ++i) {
// 创建启动线程
new Thread(new LatchWorker(startLatch, endLatch), "T" + i).start();
}
// 得到线程开始工作的时间
long start = System.nanoTime();
System.out.println("线程开始执行!");
// 主线程。递减开始计数器。让所有线程开始工作
startLatch.countDown();
// 主线程阻塞,等待所有线程完成
endLatch.await();
long end = System.nanoTime();
System.out.println("最后执行时间(MS):" + (end - start) / 1000000);
}
}
class LatchWorker implements Runnable {
// 等待启动信号
private CountDownLatch startLatch;
// 发送结束信号
private CountDownLatch endLatch;
public LatchWorker(CountDownLatch startLatch, CountDownLatch endLatch) {
this.startLatch = startLatch;
this.endLatch = endLatch;
}
@Override
public void run() {
try {
startLatch.await();
doWork();
endLatch.countDown();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void doWork() {
try {
int i = new java.util.Random().nextInt(5);
System.out.println(Thread.currentThread().getName() + " 需要" + i
+ "秒...");
TimeUnit.SECONDS.sleep(i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
线程开始执行!
T4 需要2秒...
T0 需要2秒...
T3 需要1秒...
T1 需要3秒...
T2 需要2秒...
最后执行时间(MS):3000