1.CountDownLatch
CountDownLatch一般是用于某个线程等待其他线程执行完之后,它才能执行,构造方法参数指定了计数的次数,countDown方法,当前线程调用此方法,则计数减一 ,awaint方法,调用此方法会一直阻塞当前线程,直到计时器的值为0;
代码示例转至:https://blog.youkuaiyun.com/chenchaofuck1/article/details/51596786
import java.util.concurrent.CountDownLatch;
public class Match {
// 模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。
public static void main(String[] args) throws InterruptedException {
// 开始的倒数锁
final CountDownLatch begin = new CountDownLatch(1);
// 结束的倒数锁
final CountDownLatch end = new CountDownLatch(10);
// 十名选手
for (int index = 0; index < 10; index++) {
new Thread(new player(begin, end), "player" + index).start();
}
System.out.println("Game Start");
// begin减1,计算变为0,开始游戏
begin.countDown();
// 等待end变为0,即所有选手到达终点
end.await();
System.out.println("Game Over");
}
}
import java.util.concurrent.CountDownLatch; public class player implements Runnable { // 开始的倒数锁 private final CountDownLatch begin; // 结束的倒数锁 private final CountDownLatch end; player(CountDownLatch begin, CountDownLatch end) { this.begin = begin; this.end = end; } @Override public void run() { // TODO Auto-generated method stub try { // 如果当前计数为零,则此方法立即返回。 // 等待 begin.await(); Thread.sleep((long) (Math.random() * 10000)); System.out.println(Thread.currentThread().getName() + " arrived"); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 每个选手到达终点时,end就减一 end.countDown(); } } }
2.CyclicBarrier
CyclicBarrier初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。
CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。
CyclicBarrier初始时还可带一个Runnable的参数, 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。
3.Semaphore
Semaphore 直译是信号量,可能称它是许可量更容易理解。当然,因为在计算机科学中这个名字由来已久,所以不能乱改。它的功能比较好理解,就是通过构造函数设定一个数量的许可,然后通过 acquire 方法获得许可,release 方法释放许可。它还有 tryAcquire 和 acquireUninterruptibly 方法,可以根据自己的需要选择
代码示例转至:https://blog.youkuaiyun.com/flower__1/article/details/70598305
class Pool {
private static final int MAX_AVAILABLE = 100;
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
public Object getItem() throws InterruptedException {
available.acquire();
return getNextAvailableItem();
}
public void putItem(Object x) {
if (markAsUnused(x))
available.release();
}
// Not a particularly efficient data structure; just for demo
protected Object[] items = ... whatever kinds of items being managed
protected boolean[] used = new boolean[MAX_AVAILABLE];
protected synchronized Object getNextAvailableItem() {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (!used[i]) {
used[i] = true;
return items[i];
}
}
return null; // not reached
}
protected synchronized boolean markAsUnused(Object item) {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (item == items[i]) {
if (used[i]) {
used[i] = false;
return true;
} else
return false;
}
}
return false;
}
}
总结:
CountDownLatch 是能使一组线程等另一组线程都跑完了再继续跑;CyclicBarrier 能够使一组线程在一个时间点上达到同步,可以是一起开始执行全部任务或者一部分任务。同时,它是可以循环使用的;Semaphore 是只允许一定数量的线程同时执行一段任务