引言
在多线程编程中,保障线程安全是至关重要的任务之一。除了传统的锁机制外,Java提供了一些强大的并发工具类,如CountDownLatch和Semaphore,用于解决特定场景下的线程同步问题。本文将深入探讨这些并发工具类的概念、用法以及适用场景。
CountDownLatch
CountDownLatch是一种同步工具类,用于控制一个或多个线程等待其他线程的完成。它基于一个计数器,当计数器达到0时,等待的线程会被唤醒继续执行。
CountDownLatch的基本用法
以下是一个使用CountDownLatch的示例,模拟多个线程并行执行,然后等待所有线程执行完毕:
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
int threadCount = 5;
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
System.out.println("Thread started");
// 模拟线程执行耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread finished");
latch.countDown(); // 线程完成,计数器减一
}).start();
}
latch.await(); // 等待计数器达到0
System.out.println("All threads finished");
}
}
Semaphore
Semaphore是一种信号量,用于控制同时访问某个资源的线程数量。它维护了一个许可数量,线程需要获取许可才能执行,执行完毕后释放许可。
Semaphore的基本用法
以下是一个使用Semaphore的示例,模拟了一组线程对有限资源的并发访问:
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
int threadCount = 3;
Semaphore semaphore = new Semaphore(2); // 最多允许两个线程同时执行
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
try {
semaphore.acquire(); // 获取许可
System.out.println("Thread acquired a permit");
// 模拟线程执行耗时操作
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放许可
System.out.println("Thread released a permit");
}
}).start();
}
}
}
CountDownLatch vs. Semaphore
CountDownLatch用于等待其他线程的执行完毕,适合一次性的等待。Semaphore用于控制并发线程数量,适合限制资源的并发访问。
适用场景
- 使用
CountDownLatch可以等待多个线程的任务都完成后再继续执行后续操作,如并行计算的结果汇总。 - 使用
Semaphore可以控制资源的并发访问数量,如连接池的控制。
总结
CountDownLatch和Semaphore是Java提供的两个强大的并发工具类,用于解决多线程编程中的线程同步问题。CountDownLatch用于等待其他线程的完成,Semaphore用于控制并发线程数量。开发者在多线程编程中,可以根据实际需求选择合适的并发工具类,保障线程安全和资源的合理利用。