更多 Java 并发编程方面的文章,请参见文集《Java 并发编程》
所在包:java.util.concurrent
CountDownLatch
类似计数器的功能,比如某个线程任务 (开饭),需要等待其他 5 个线程任务(做 5 道菜)执行完才能执行。
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
-
public CountDownLatch(int count)
构造方法,设置计数器个数 -
void await()
线程阻塞,直到计数器 count 为 0 -
boolean await(long timeout, TimeUnit unit)
线程阻塞一段时间,直到计数器 count 为 0。如果超时,线程结束阻塞,继续执行。 -
void countDown()
计数器 count 减 1 -
long getCount()
得到当前计数器 count
示例:
线程任务 (开饭),需要等待其他 5 个线程任务(做 5 道菜)执行完才能执行
public class CountDownLatch_Test {
private static CountDownLatch countDownLatch = new CountDownLatch(5);
public static void main(String[] args) {
new EatThread().start();
for (int i = 0; i < 5; i++) {
new DishThread().start();
}
}
static class DishThread extends Thread {
public void run() {
try {
System.out.println("Making dish");
Thread.sleep(1000);
// 计数器 count 减 1
countDownLatch.countDown();
} catch (InterruptedException e) {
}
}
}
static class EatThread extends Thread {
public void run() {
try {
// 线程阻塞,直到计数器 count 为 0
countDownLatch.await();
System.out.println("Start eating");
} catch (InterruptedException e) {
}
}
}
}
CyclicBarrier
N 个线程互相等待,任何一个线程达到某个状态之前,所有的线程都必须等待。
必须等到所有线程都达到某个状态,这 N 个线程才能继续执行。
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
-
public CyclicBarrier(int parties)
构造方法,设置参与的线程数目 -
public CyclicBarrier(int parties, Runnable barrierAction)
构造方法,设置参与的线程数目,barrierAction 为参与的线程都到达 barrier point 之后会执行的操作。 -
int await()
线程阻塞,到达 barrier point,等到其他参与的线程也调用await()
到达 barrier point -
int await(long timeout, TimeUnit unit)
线程阻塞一段时间,到达 barrier point,等到其他参与的线程也调用await()
到达 barrier point。如果超时,线程结束阻塞,继续执行。
示例:
5个旅行者相约从全国各地到北京汇合,每个人路上花的时间不同,等都汇合后一起去上海。
public class CyclicBarrier_Test {
private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
new Traveler(i).start();
}
}
static class Traveler extends Thread {
private int travel_time;
public Traveler(int travel_time) {
this.travel_time = travel_time;
}
public void run() {
try {
Thread.sleep(travel_time * 1000);
System.out.println("Traveler " + Thread.currentThread().getId() + " spends " + travel_time + " to arrive Beijing.");
// 等待其他人来北京汇合
cyclicBarrier.await();
// 都汇合后一起去上海
System.out.println("All travelers arrived at Beijing, let's go to Shanghai");
} catch (Exception e) {
}
}
}
}
输出如下:
Traveler 11 spends 1 to arrive Beijing.
Traveler 12 spends 2 to arrive Beijing.
Traveler 13 spends 3 to arrive Beijing.
Traveler 14 spends 4 to arrive Beijing.
Traveler 15 spends 5 to arrive Beijing.
All travelers arrived at Beijing, let's go to Shanghai
All travelers arrived at Beijing, let's go to Shanghai
All travelers arrived at Beijing, let's go to Shanghai
All travelers arrived at Beijing, let's go to Shanghai
All travelers arrived at Beijing, let's go to Shanghai