Semaphore通过许可机制限制并发访问线程数,acquire()获取许可,release()释放许可,确保资源安全。

在Java中,Semaphore 是并发编程中用于控制对共享资源访问数量的工具类,常用于限流、资源池管理等场景。它通过维护一组许可(permits)来限制同时访问特定资源的线程数量。
Semaphore的基本原理
Semaphore内部维护了一个计数器,表示可用许可的数量。线程在访问资源前必须先获取许可,如果当前没有可用许可,线程将被阻塞,直到其他线程释放许可为止。
主要方法包括:
- acquire():尝试获取一个许可,如果没有可用许可,线程会阻塞。
- acquire(int permits):一次获取多个许可。
- release():释放一个许可,使其他等待的线程有机会获得许可。
- release(int permits):一次释放多个许可。
- availablePermits():返回当前可用的许可数。
简单使用示例:限制并发线程数
假设我们有一个服务最多允许3个线程同时访问,可以使用Semaphore进行控制:
立即学习“Java免费学习笔记(深入)”;
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
// 定义一个拥有3个许可的Semaphore
private static final Semaphore semaphore = new Semaphore(3);
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " 尝试获取许可");
semaphore.acquire(); // 获取许可
System.out.println(Thread.currentThread().getName() + " 获得许可,开始执行任务");
// 模拟任务执行
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " 任务完成,释放许可");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release(); // 释放许可
}
}, "Thread-" + i).start();
}
}
}
在这个例子中,尽管启动了5个线程,但只有3个能同时运行,其余线程需等待许可释放后才能执行。
应用场景与注意事项
Semaphore适用于以下场景:
使用时需要注意:
- 确保每次acquire()后都有对应的release(),建议放在finally块中,避免死锁或资源泄露。
- 初始化许可数应根据实际资源容量设置,过大失去限流意义,过小影响并发性能。
- Semaphore默认是非公平的,可传入true构造公平模式,避免线程饥饿。
基本上就这些,掌握好acquire和release的配对使用,就能有效实现资源的并发控制。不复杂但容易忽略细节。










