转自:
http://www.java265.com/JavaCourse/202204/3184.html
下文笔者讲述java中Semaphore类的详解说明,如下所示:
Semaphore简介
Semaphore(中文翻译:信号量)
我们常用于控制访问某一资源的线程个数,
使用这种方式可使大家按照一定的规则访问某一资源
Semaphore的原理:
通过使用计数器来控制对某一资源的访问
当计数器大于0,则允许访问
当计数器为0时,则拒绝访问
计数器中的计数作为允许访问共享资源的许可
即:访问资源,需从信号量中授予线程许可
Semaphore方法
| 方法名 | 备注 |
| void acquire() | 从信号量获取一个许可,在无可用许可前,将一直阻塞等待 |
| void acquire(int permits) | 获取指定数目的许可,在无可用许可前,也将会一直阻塞等待 |
| boolean tryAcquire() | 从信号量尝试获取一个许可,当无可用许可,直接返回false,不会阻塞 |
| boolean tryAcquire(int permits) | 尝试获取指定数目的许可,当无可用许可直接返回false |
| boolean tryAcquire(int permits, long timeout, TimeUnit unit) | 在指定的时间内尝试从信号量中获取许可,当在指定的时间内获取成功,返回true,否则返回false |
| void release() | 释放一个许可,别忘了在finally中使用 注意:多次调用该方法,会使信号量的许可数增加,达到动态扩展的效果 如:初始permits为1,调用了两次release,最大许可会改变为2 |
| int availablePermits() | 获取当前信号量可用的许可 |
Semaphore构造函数
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
参数说明:
permits:初始许可数,即最大访问线程数
fair:当设置为false时,创建的信号量为非公平锁;当设置为true时,信号量是公平锁
使用Semaphore限制登录的最大用户数
package com.java265.other;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class Test16 {
public static void main(String[] args) {
// 允许最大的获取用户的线程数
int slots = 8;
ExecutorService executorService = Executors.newFixedThreadPool(slots);
UserUsingSemaphore loginQueue = new UserUsingSemaphore(slots);
// 线程池模拟登录
for (int i = 1; i <= slots; i++) {
final int num = i;
executorService.execute(() -> {
if (loginQueue.tryAcquire()) {
System.out.println("用户:" + num + "获取成功!");
} else {
System.out.println("用户:" + num + "获取失败!");
}
});
}
executorService.shutdown();
System.out.println("当前可用许可证数:" + loginQueue.availableSlots());
// 此时已经有8个线程,再次获取的时候会返回false
if (loginQueue.tryAcquire()) {
System.out.println("获取成功!");
} else {
System.out.println("资源已经被占满,获取失败!");
}
// 有用户释放资源,只释放一个资源
loginQueue.releaseAcquire();
// 再次获取
if (loginQueue.tryAcquire()) {
System.out.println("获取成功-2!");
} else {
System.out.println("资源已经被占满,获取失败-2!");
}
// 再次获取-会失败,因为又没有空余
if (loginQueue.tryAcquire()) {
System.out.println("获取成功-3!");
} else {
System.out.println("资源已经被占满,获取失败-3!");
}
}
}
/*
* 定义一个登录队列,用于获取信号量
*/
class UserUsingSemaphore {
private Semaphore semaphore;
/**
* @param 设置信号量的大小
*/
public UserUsingSemaphore(int slotLimit) {
semaphore = new Semaphore(slotLimit);
}
boolean tryAcquire() {
// 获取一个凭证
return semaphore.tryAcquire();
}
/*
* 释放凭证
*/
void releaseAcquire() {
semaphore.release();
}
/*
* 获取可用的凭证数量
*/
int availableSlots() {
return semaphore.availablePermits();
}
}
------运行以上代码,将输出以下信息------
用户:1获取成功!
用户:5获取成功!
用户:2获取成功!
用户:4获取成功!
用户:3获取成功!
用户:7获取成功!
用户:6获取成功!
当前可用许可证数:1
资源已经被占满,获取失败!
获取成功-2!
资源已经被占满,获取失败-3!
用户:8获取成功!
原创文章,作者:jamestackk,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/273848.html