Semaphore的简介及应用场景
Semaphore是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。
常用函数:
信号量的构造函数
非公平:
public Semaphore(int permits);//permits就是允许同时运行的线程数目
公平(获得锁的顺序与线程启动顺序有关):
public Semaphore(int permits,boolean fair);//permits就是允许同时运行的线程数目
创建一个信号量
Semaphore semaphore = new Semaphore(2);
从信号量中获取一个许可
semaphore.acquire();
释放一个许可(在释放许可之前,必须先获获得许可。)
semaphore.release();
尝试获取一个许可,若获取成功返回true,若获取失败返回false
semaphore.tryAcquire();
所有函数:
// 创建具有给定的许可数和非公平的公平设置的 Semaphore。
Semaphore(int permits)
// 创建具有给定的许可数和给定的公平设置的 Semaphore。
Semaphore(int permits, boolean fair) // 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
void acquire()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。
void acquire(int permits)
// 从此信号量中获取许可,在有可用的许可前将其阻塞。
void acquireUninterruptibly()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
void acquireUninterruptibly(int permits)
// 返回此信号量中当前可用的许可数。
int availablePermits()
// 获取并返回立即可用的所有许可。
int drainPermits()
// 返回一个 collection,包含可能等待获取的线程。
protected Collection<Thread> getQueuedThreads()
// 返回正在等待获取的线程的估计数目。
int getQueueLength()
// 查询是否有线程正在等待获取。
boolean hasQueuedThreads()
// 如果此信号量的公平设置为 true,则返回 true。
boolean isFair()
// 根据指定的缩减量减小可用许可的数目。
protected void reducePermits(int reduction)
// 释放一个许可,将其返回给信号量。
void release()
// 释放给定数目的许可,将其返回到信号量。
void release(int permits)
// 返回标识此信号量的字符串,以及信号量的状态。
String toString()
// 仅在调用时此信号量存在一个可用许可,才从信号量获取许可。
boolean tryAcquire()
// 仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。
boolean tryAcquire(int permits)
// 如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。
boolean tryAcquire(int permits, long timeout, TimeUnit unit)
// 如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可。
boolean tryAcquire(long timeout, TimeUnit unit)
代码实例:
假设有10个人在银行办理业务,只有2个工作窗口,代码实现逻辑如下
public class SemaphoreDemo {
// 排队总人数(请求总数)
public static int clientTotal = 10;
// 可同时受理业务的窗口数量(同时并发执行的线程数)
public static int threadTotal = 2;
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
final int count = i;
executorService.execute(() -> {
try {
semaphore.acquire(1);
resolve(count);
semaphore.release(2);
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
}
private static void resolve(int i) throws InterruptedException {
log.info("服务号{},受理业务中。。。", i);
Thread.sleep(2000);
}
}
输出结果:
21:39:10.038 [pool-1-thread-1] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号0,受理业务中。。。
21:39:10.038 [pool-1-thread-2] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号1,受理业务中。。。
21:39:12.043 [pool-1-thread-4] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号3,受理业务中。。。
21:39:12.043 [pool-1-thread-3] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号2,受理业务中。。。
21:39:14.044 [pool-1-thread-6] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号5,受理业务中。。。
21:39:14.044 [pool-1-thread-5] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号4,受理业务中。。。
21:39:16.045 [pool-1-thread-7] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号6,受理业务中。。。
21:39:16.045 [pool-1-thread-8] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号7,受理业务中。。。
21:39:18.045 [pool-1-thread-10] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号9,受理业务中。。。
21:39:18.045 [pool-1-thread-9] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号8,受理业务中。。。
从输出结果可以看出,每隔两秒,有两个线程被执行
原文链接:https://blog.csdn.net/yuruixin_china/article/details/82084946
Semaphore是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。
常用函数: 信号量的构造函数 非公平:
public Semaphore(int permits);//permits就是允许同时运行的线程数目1公平(获得锁的顺序与线程启动顺序有关):
public Semaphore(int permits,boolean fair);//permits就是允许同时运行的线程数目1创建一个信号量
Semaphore semaphore = new Semaphore(2);1从信号量中获取一个许可
semaphore.acquire();1释放一个许可(在释放许可之前,必须先获获得许可。)
semaphore.release();1尝试获取一个许可,若获取成功返回true,若获取失败返回false
semaphore.tryAcquire();1所有函数:
// 创建具有给定的许可数和非公平的公平设置的 Semaphore。Semaphore(int permits)// 创建具有给定的许可数和给定的公平设置的 Semaphore。Semaphore(int permits, boolean fair)
// 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。void acquire()// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。void acquire(int permits)// 从此信号量中获取许可,在有可用的许可前将其阻塞。void acquireUninterruptibly()// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。void acquireUninterruptibly(int permits)// 返回此信号量中当前可用的许可数。int availablePermits()// 获取并返回立即可用的所有许可。int drainPermits()// 返回一个 collection,包含可能等待获取的线程。protected Collection<Thread> getQueuedThreads()// 返回正在等待获取的线程的估计数目。int getQueueLength()// 查询是否有线程正在等待获取。boolean hasQueuedThreads()// 如果此信号量的公平设置为 true,则返回 true。boolean isFair()// 根据指定的缩减量减小可用许可的数目。protected void reducePermits(int reduction)// 释放一个许可,将其返回给信号量。void release()// 释放给定数目的许可,将其返回到信号量。void release(int permits)// 返回标识此信号量的字符串,以及信号量的状态。String toString()// 仅在调用时此信号量存在一个可用许可,才从信号量获取许可。boolean tryAcquire()// 仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。boolean tryAcquire(int permits)// 如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。boolean tryAcquire(int permits, long timeout, TimeUnit unit)// 如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可。boolean tryAcquire(long timeout, TimeUnit unit)1234567891011121314151617181920212223242526272829303132333435363738394041代码实例: 假设有10个人在银行办理业务,只有2个工作窗口,代码实现逻辑如下
package com..concurrency.yuxin.demo;
import lombok.extern.slf4j.Slf4j;import org.joda.time.DateTime;import org.joda.time.format.DateTimeFormat;import org.joda.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;
@Slf4jpublic class SemaphoreDemo {
// 排队总人数(请求总数) public static int clientTotal = 10;
// 可同时受理业务的窗口数量(同时并发执行的线程数) public static int threadTotal = 2;
public static void main(String[] args) throws Exception { ExecutorService executorService = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(threadTotal); final CountDownLatch countDownLatch = new CountDownLatch(clientTotal); for (int i = 0; i < clientTotal; i++) { final int count = i; executorService.execute(() -> { try { semaphore.acquire(1); resolve(count); semaphore.release(2); } catch (Exception e) { log.error("exception", e); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); }
private static void resolve(int i) throws InterruptedException { log.info("服务号{},受理业务中。。。", i); Thread.sleep(2000); }}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849输出结果:
21:39:10.038 [pool-1-thread-1] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号0,受理业务中。。。21:39:10.038 [pool-1-thread-2] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号1,受理业务中。。。21:39:12.043 [pool-1-thread-4] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号3,受理业务中。。。21:39:12.043 [pool-1-thread-3] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号2,受理业务中。。。21:39:14.044 [pool-1-thread-6] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号5,受理业务中。。。21:39:14.044 [pool-1-thread-5] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号4,受理业务中。。。21:39:16.045 [pool-1-thread-7] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号6,受理业务中。。。21:39:16.045 [pool-1-thread-8] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号7,受理业务中。。。21:39:18.045 [pool-1-thread-10] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号9,受理业务中。。。21:39:18.045 [pool-1-thread-9] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号8,受理业务中。。。12345678910从输出结果可以看出,每隔两秒,有两个线程被执行--------------------- 版权声明:本文为CSDN博主「yuruixin_china」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/yuruixin_china/article/details/82084946
Semaphore的简介及应用场景的更多相关文章
- [转帖]kafka入门:简介、使用场景、设计原理、主要配置及集群搭建
kafka入门:简介.使用场景.设计原理.主要配置及集群搭建 http://www.aboutyun.com/thread-9341-1-1.html 还没看完 感觉挺好的. 问题导读: 1.zook ...
- kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)
问题导读: 1.zookeeper在kafka的作用是什么? 2.kafka中几乎不允许对消息进行"随机读写"的原因是什么? 3.kafka集群consumer和producer状 ...
- 开放数据接口 API 简介与使用场景、调用方法
此文章对开放数据接口 API 进行了功能介绍.使用场景介绍以及调用方法的说明,供用户在使用数据接口时参考之用. 在给大家分享的一系列软件开发视频课程中,以及在我们的社区微信群聊天中,都积极地鼓励大家开 ...
- RabbitMQ 简介以及使用场景
目录 一. RabbitMQ 简介 二. RabbitMQ 使用场景 1. 解耦(为面向服务的架构(SOA)提供基本的最终一致性实现) 2. 异步提升效率 3. 流量削峰 三. 引入消息队列的优缺点 ...
- 浅谈nginx简介和应用场景
简介 nginx是一款轻量级的web服务器,它是由俄罗斯的程序设计师伊戈尔·西索夫所开发. nginx相比于Tomcat性能十分优秀,能够支撑5w的并发连接(而Tomcat只能支撑200-400),并 ...
- 中间件 | kafka简介、使用场景、设计原理、主要配置及集群搭建
开源Java学习 公众号 一.入门 1.简介 Kafka is a distributed,partitioned,replicated commit logservice.它提供了类似于JMS的特性 ...
- Redis简介,应用场景,优势
Redis简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久化 ...
- 01 . etcd简介原理,应用场景及部署,简单使用
etcd简介 Etcd是CoreOS团队于2013年6月发起的开源项目,他的目标是构建一个高可用的分布式键值(key-value)数据库,etcd内部采用raft协议作为一致性算法,etcd基于Go语 ...
- spark第一篇--简介,应用场景和基本原理
摘要: spark的优势:(1)图计算,迭代计算(2)交互式查询计算 spark特点:(1)分布式并行计算框架(2)内存计算,不仅数据加载到内存,中间结果也存储内存 为了满足挖掘分析与交互式实时查询的 ...
随机推荐
- 2019 SDN上机第3次作业
1. 利用Mininet仿真平台构建如下图所示的网络拓扑,配置主机h1和h2的IP地址(h1:10.0.0.1,h2:10.0.0.2),测试两台主机之间的网络连通性 创建拓扑 配置主机h1和h2的I ...
- [LeetCode] 130. Surrounded Regions 包围区域
Given a 2D board containing 'X' and 'O'(the letter O), capture all regions surrounded by 'X'. A regi ...
- 3,[VS] 编程时的有必要掌握的小技巧_______________________________请从下面第 1 篇看起
本文导览: 善用“并排显示窗口”功能 做作业/测试时使用 多项目 多个源文件 多个子函数 使用Visual Studio team代码同步工具,及时把项目文件保存到云端 关闭括号分号自动联想 技巧是提 ...
- docker环境下数据库的备份(postgresql, mysql)
posgresql 备份/恢复 mysql 备份/恢复 补充 posgresql 备份/恢复 备份 DATE=`date +%Y%m%d-%H%M` BACK_DATA=xxapp-data-${DA ...
- python运维开发常用模块(5)文件目录对比模块filecmp
1.filecmp模块介绍 当我们进行代码审计或校验备份结果时,往往需要检查原始与目 标目录的文件一致性,Python的标准库已经自带了满足此需求的模块 filecmp.filecmp可以实现文件.目 ...
- 通过欧拉计划学Rust(第1~6题)
最近想学习Libra数字货币的MOVE语言,发现它是用Rust编写的,看来想准确理解MOVE的机制,还需要对Rust有深刻的理解,所以开始了Rust的快速入门学习. 看了一下网上有关Rust的介绍,都 ...
- prometheus exporter简介
一.服务分类 在线服务:请求的客户端和发起者需要立即响应(高并发.低延迟:并发数.接口响应时间.错误数.延迟时间),面对突发流量能进行资源的自动伸缩 离线服务:请求发送到服务端但不要求立即获取结果(监 ...
- SpringBoot 系列教程自动配置选择生效
191214-SpringBoot 系列教程自动配置选择生效 写了这么久的 Spring 系列博文,发现了一个问题,之前所有的文章都是围绕的让一个东西生效:那么有没有反其道而行之的呢? 我们知道可以通 ...
- MySQL子查询结果集是否有记录
Mark SELECT tu.id userId, tu.avatar_url avatarUrl, tu.wx_nick_name wxNickName, tu.city city, (select ...
- Phaser铁人三项
/** * 模拟铁人三项 */ public class PhaserTest { private static Random random = new Random(System.currentTi ...