1.CountDownLatch
你可以向CountDownLatch对象提供一个初始值,任何在这个对象上调用wait()的方法都将阻塞,直至这个计数值达到为0。其他任务在结束其工作时,可以调用其countLatch()来减少这个数值。CountDownLatch被设计为只能触发一次,计数值不能被重置。
代码:
这个Runnable用于结束任务时调用countLatch()方法,表示任务执行次数加一,到达初始值后会统一放行调用wait()方法的任务
@Override
public void run() {
try {
doWork();
latch.countDown();
} catch (InterruptedException e) {
}
}
这个Runnable用于调用wait()等待目标任务完成后再执行
@Override
public void run() {
try {
latch.await();
System.out.println("Latch barrier passed for " + this);
} catch (InterruptedException e) {
System.out.println(this + " interrupted");
}
}
2.CyclicBarrier(栅栏动作)
CyclicBarrier适用于这样的情况,你希望创建一个任务,他们并行的执行工作,然后在进行下一个动作前等待,直至所有任务完成。他使得所有并行任务都在栅栏处等待,因此可以一致的向前移动,CyclicBarrier可以多次重用
代码:(跑马比赛,到总点结束比赛,所有马停止跑步)
这个任务是horse跑步,但是每秒跑完后都会调用await()方法,进行阻塞,因为他们是CyclicBarrier,其每次调用await都会使其值减一,当其初始值为0时会执行栅栏动作(一个匿名内部类Runnable),当执行完栅栏动作后会重新使阻塞的动作的并行任务重新恢复运行
@Override
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
strides += random.nextInt(3);
}
barrier.await();
}
} catch (InterruptedException e) {
//
} catch (BrokenBarrierException e) {
throw new RuntimeException();
}
new CyclicBarrier(nHorses, new Runnable())
其中nHorse是初始值,Runnable是栅栏动作,在栅栏动作中可以调用shutdownNow使得阻塞的并行任务死亡,从而结束任务
public HoseRace(int nHorses, final int pause) {
barrier = new CyclicBarrier(nHorses, new Runnable() {
@Override
public void run() {
StringBuilder s = new StringBuilder();
for (int i = 0; i < FINISH_LINE; i++)
s.append("=");
System.out.println(s);
for (Horse horse : horses)
if (horse.getStrides() >= FINISH_LINE) {
System.out.println(horse + "won!");
exec.shutdownNow();
return;
}
try {
TimeUnit.MILLISECONDS.sleep(pause);
} catch (InterruptedException e) {
System.out.println("barrier-action sleep interrupted");
}
}
});
for (int i = 0; i < nHorses; i++) {
Horse horse = new Horse(barrier);
horses.add(horse);
exec.execute(horse);
}
}