CountDownLatch
、CyclicBarrier
和Semaphore
是Java并发包中的三种常用同步工具,它们在多线程编程中有各自的特定用途。以下是它们的详细介绍和示例代码:
1. CountDownLatch
CountDownLatch
是一个同步辅助类,用于使一个或多个线程等待直到其他线程中的操作执行完毕。- 它的核心概念是一个计数器,线程可以通过调用
countDown()
方法来减少计数器,- 当计数器到达零时,所有等待(await();)的线程会被唤醒。
示例:主线程等待多个线程完成
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
int numberOfThreads = 3;
CountDownLatch latch = new CountDownLatch(numberOfThreads);
for (int i = 0; i < numberOfThreads; i++) {
new Thread(new Worker(latch)).start();
}
// 等待所有工人完成任务
latch.await();
System.out.println("All workers have finished their tasks.");
}
static class Worker implements Runnable {
private final CountDownLatch latch;
Worker(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
// 模拟任务处理
Thread.sleep((long) (Math.random() * 1000));
System.out.println(Thread.currentThread().getName() + " finished its task.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
latch.countDown();
}
}
}
}
2. CyclicBarrier
CyclicBarrier
是一个同步辅助类,它允许一组线程相互等待(await()),直到它们都到达一个共同的屏障点。- 与
CountDownLatch
不同的是,CyclicBarrier
可以重复使用。
示例:多个线程相互等待,直到所有线程都到达屏障点
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
int numberOfThreads = 3;
CyclicBarrier barrier = new CyclicBarrier(numberOfThreads, () -> {
System.out.println("All parties have arrived at barrier, let's proceed.");
});
for (int i = 0; i < numberOfThreads; i++) {
new Thread(new Worker(barrier)).start();
}
}
static class Worker implements Runnable {
private final CyclicBarrier barrier;
Worker(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
try {
// 模拟任务处理
Thread.sleep((long) (Math.random() * 1000));
System.out.println(Thread.currentThread().getName() + " reached the barrier.");
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
}
}
}
3. Semaphore
Semaphore
是一个计数信号量,用于控制对某个资源的访问。- 它维护了一个许可集,线程可以通过调用
acquire()
方法获取许可,调用release()
方法释放许可。- 当没有许可可用时,调用
acquire()
的线程会被阻塞。
示例:限制对资源的并发访问
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
int numberOfPermits = 3;
Semaphore semaphore = new Semaphore(numberOfPermits);
for (int i = 0; i < 10; i++) {
new Thread(new Worker(semaphore)).start();
}
}
static class Worker implements Runnable {
private final Semaphore semaphore;
Worker(Semaphore semaphore) {
this.semaphore = semaphore;
}
@Override
public void run() {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " acquired a permit.");
// 模拟任务处理
Thread.sleep((long) (Math.random() * 1000));
System.out.println(Thread.currentThread().getName() + " released a permit.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release();
}
}
}
}
总结
CountDownLatch
:用于一个或多个线程等待其他线程完成操作。计数器到达零时,所有等待的线程都会被唤醒。CyclicBarrier
:用于一组线程相互等待,直到所有线程都到达屏障点。屏障可以重复使用。Semaphore
:用于控制对资源的并发访问,通过许可机制实现。线程可以获取和释放许可,当没有许可可用时,线程会被阻塞。