当前位置: 代码迷 >> 综合 >> Java 并发工具类之 Semaphore
  详细解决方案

Java 并发工具类之 Semaphore

热度:35   发布时间:2023-12-26 12:53:55.0

Semaphore 控制访问特定资源的线程数量,新建规定数量的许可证,获得许可证可以继续执行,未获得需要阻塞,执行完成归还许可证,这样其余的线程(未获得许可证)才可以执行。例如:Semaphore用于流量控制,例如只有10个数据库连接,可以用Semaphore控制只有10个线程访问数据库,这样就不会报错无法获取数据库连接。

 1. Semaphore的部分方法

方法 描述
public Semaphore(int permits) 构造函数:设置许可证数permits。
public Semaphore(int permits, boolean fair) 设置许可证数permits, fair 为 true 使用先进先出的公平策略,false则不公平。
public void acquire() 获取许可证。
public void acquireUninterruptibly()  不可中断的获取许可证。
public boolean tryAcquire() 尝试获取许可证,没有许可证不阻塞
public boolean tryAcquire(long timeout, TimeUnit unit) 等待一定时间,一直没有获得许可证不再阻塞
public void release() 归还许可证
public void acquire(int permits) 获取给定数量的许可证
public void release(int permits) 归还给定数量的许可证
public final boolean hasQueuedThreads() 是否有线程在等待
public final int getQueueLength() 等待线程的数量
protected Collection<Thread> getQueuedThreads() 返回所有等待许可的线程集合
public int availablePermits() 剩余许可证

2. 测试代码

许可证数量初始为 3 。

private static Semaphore semaphore = new Semaphore(3);

测试代码如下所示,开启10个线程获取数据库连接,因为只有三个许可证,三个许可证被获取后,其他线程需要等待当前的三个线程释放许可证才可以获取许可证,所以三个数据库连接、三个数据库连接被获取: 

public class SemaphoreStudy implements Runnable{private static Semaphore semaphore = new Semaphore(3);@Overridepublic void run() {try {semaphore.acquire();System.out.print("获得数据库连接");TimeUnit.MILLISECONDS.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}semaphore.release();}public static void main(String[] args) {for (int i=0; i<10; i++) {;new Thread(new SemaphoreStudy()).start();}}
}

运行截图,三个、三个数据库连接被获取。

使用 tryAcquire() 进行修改, tryAcquire() 尝试获取许可证,没有许可证不阻塞,测试代码如下:

public class SemaphoreStudy implements Runnable{private static Semaphore semaphore = new Semaphore(3);@Overridepublic void run() {try {if (semaphore.tryAcquire()) {System.out.println("获得数据库连接");TimeUnit.MILLISECONDS.sleep(1000);semaphore.release();}} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {for (int i=0; i<10; i++) {;new Thread(new SemaphoreStudy()).start();}}
}

运行截图,7个获取不到许可证的线程,不阻塞等待:

  相关解决方案