转自:
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获取成功!
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |