一、什么是 Semaphore
Semaphore 也叫信号量,在 JDK1.5 被引入,主要用于在多个线程访问多个共享资源的场景下,通过协调各个线程,来保证合理的资源访问。 例如数量有限的餐厅桌椅,银行业务办理窗口等。
二、Semaphore 常用 APi
方法 | 说明 |
acquire() | 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被 中断 |
acquire(int permits) | 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断 |
release() | 释放一个许可,将可用的许可数增加 1 |
release(int permits) | 释放给定数目的许可,将其返回到信号量 |
isFair() | 如果此信号量的公平设置为 true,则返回 true |
三、代码示例
例如:工厂只有 5 台机器,每台机器限一人使用,现对 8 名工人进行资源分配:
public class SemaphoreTest {
public static void main(String[] args) {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
// 只有5台机器
final Semaphore semp = new Semaphore(5);
// 模拟8 个工人工作
for (int i = 0; i < 8; i++) {
final int emp_num = i;
Runnable run = new Runnable() {
public void run() {
try {
// 获取许可
semp.acquire();
System.out.println("获得许可,当前工作工人: " + emp_num);
Thread.sleep((long) (Math.random() * 10000));
// 访问完后,释放
semp.release();
System.out.println("释放资源,当前空闲机器数量:" + semp.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
exec.execute(run);
}
// 退出线程池
exec.shutdown();
}
}
结果打印:
获得许可,当前工作工人: 4
获得许可,当前工作工人: 3
获得许可,当前工作工人: 1
获得许可,当前工作工人: 2
获得许可,当前工作工人: 0
释放资源,当前空闲机器数量:1
获得许可,当前工作工人: 5
释放资源,当前空闲机器数量:1
获得许可,当前工作工人: 7
释放资源,当前空闲机器数量:1
获得许可,当前工作工人: 6
释放资源,当前空闲机器数量:1
释放资源,当前空闲机器数量:2
释放资源,当前空闲机器数量:3
释放资源,当前空闲机器数量:4
释放资源,当前空闲机器数量:5
另外:在创建Semaphore对象的时候还可以指定它的公平性。一般常用非公平的信号量,非公平信号量是指在获取许可时先尝试获取许可,而不必关心是否已有需要获取许可的线程位于等待队列中,如果获取失败,才会入列。而公平的信号量在获取许可时首先要查看等待队列中是否已有线程,如果有则入列。
公平信号量的创建方式: Semaphore semaphore = new Semaphore(5,true);