同步屏障CyclicBarrier
/ˈsaɪklɪk ˈbæriə(r)/
CyclicBarrier的字面意思是可循环(Cyclic)使用的屏障(Barrier)。让一组线程到达一个屏障(也叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会打开。
线程调用await()方法会被阻塞,直到所有线程到达屏障时,屏障才会打开
其他API:
cyclicBarrier.getNumberWaiting()获取阻塞线程数
cyclicBarrier.isBroken()了解阻塞线程是否被中断
例子:集齐7龙珠就可以召唤神龙。未集齐则阻塞main线程
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, ()->{
System.out.println("7龙珠集齐完毕,召唤神龙");
});
for (int i = 1; i <= 7; i++) {
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName() + "找到一颗龙珠!");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},"t" + i).start();
}
等待多线程完成CountDownLatch
使用join
join()方法,底层调用wait()方法,让当前线程阻塞。当前线程执行完毕后,JVM内部会唤醒该线程,比如调用当前线程的notifyAll()方法
Thread t1 = new Thread(()->{
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("t1执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(()->{
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("t2执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("main线程执行完毕");
结果:
t2执行完毕
t1执行完毕
main线程执行完毕
使用CountDownLatch
CountDownLatch主要有两个方法,调用await方法的线程会阻塞,调用countDown方法的线程不会阻塞,计算器会减1。当计数器为0时,因为调用await方法被阻塞的线程会被唤醒,继续执行。
CountDownLatch countDownLatch = new CountDownLatch(2);
Thread t1 = new Thread(()->{
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("t1执行完毕");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(()->{
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("t2执行完毕");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
countDownLatch.await();
System.out.println("main线程执行完毕");
控制线程并发数量Semaphore
可用作流量控制