Semaphore (信号量)是用来控制同 时访问 特定 资 源的 线 程数量,它通 过协调 各个 线 程,以
保 证 合理的使用公共 资 源。
计数信号灯。从概念上讲,信号量维护一组许可。每个{@link#acquire}都会在必要时阻塞,直到有许可证可用,然后再获取它。每个{@link#release}都会添加一个许可证,可能会释放一个阻塞收单机构。但是,没有使用实际的许可证对象;{@code信号量}只保留可用数量的计数,并相应地进行操作。
应用场景:
Semaphore 可以用于做流量控制,特 别 是公用 资 源有限的 应 用 场 景,比如数据 库连 接。假
如有一个需求,要 读 取几万个文件的数据,因 为 都是 IO 密集型任 务 ,我 们 可以启 动 几十个 线 程
并 发 地 读 取,但是如果 读 到内存后, 还 需要存 储 到数据 库 中,而数据 库 的 连 接数只有 10 个, 这
时 我 们 必 须 控制只有 10 个 线 程同 时获 取数据 库连 接保存数据,否 则 会 报错 无法 获 取数据 库连
接。 这 个 时 候,就可以使用 Semaphore 来做流量控制
package com.netty.obj.demo5.d4;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @PackageName:com.netty.obj.demo5.d4 Description
* @author:
* @date:2022/1/12
*/
public class SemaphoreTest {
private static final int THREAD_COUNT = 30;
private static ExecutorService threadPool =Executors.newFixedThreadPool(THREAD_COUNT);
private static Semaphore s = new Semaphore(10);
public static void main(String[] args) {
for (int i = 0; i < THREAD_COUNT; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
s.acquire();
System.out.println("save data");
s.release();
} catch (InterruptedException e) {
}
}
});
}
threadPool.shutdown();
}
}
在代 码 中, 虽 然有 30 个 线 程在 执 行,但是只允 许 10 个并 发执 行。 Semaphore 的构造方法
Semaphore ( int permits )接受一个整型的数字,表示可用的 许 可 证 数量。 Semaphore ( 10 )表示允
许 10 个 线 程 获 取 许 可 证 ,也就是最大并 发 数是 10 。 Semaphore 的用法也很 简单 ,首先 线 程使用
Semaphore 的 acquire() 方法 获 取一个 许 可 证 ,使用完之后 调 用 release() 方法 归还许 可 证 。 还 可以
用 tryAcquire() 方法 尝试获 取 许 可 证 。
Semaphore 还 提供一些其他方法,具体如下。
·intavailablePermits() :返回此信号量中当前可用的 许 可 证 数。
·intgetQueueLength() :返回正在等待 获 取 许 可 证 的 线 程数。
·booleanhasQueuedThreads() :是否有 线 程正在等待 获 取 许 可 证 。
·void reducePermits ( int reduction ):减少 reduction 个 许 可 证 ,是个 protected 方法。
·Collection getQueuedThreads() :返回所有等待 获 取 许 可 证 的 线 程集合,是个 protected 方
法。
总结:案例来源《Java并发编程的艺术》,主要熟悉Semaphore的业务应用场景,希望有帮助。