java 多线程 28 : 多线程组件之 Semaphore 信号量
Semaphore是非常有用的一个组件,它相当于是一个并发控制器,是用于管理信号量的。构造的时候传入可供管理的信号量的数值,这个数值就是控制并发数量的,就是同时能几个线程访问。我们需要控制并发的代码,执行前先通过acquire方法获取信号,执行后通过release归还信号 。每次acquire返回成功后,Semaphore可用的信号量就会减少一个,如果没有可用的信号,acquire调用就会阻塞,等待有release调用释放信号后,acquire才会得到信号并返回。
ps:注意这里信号量acquire方法和release方法是可以有参数的,表示获取/返还的信号量个数,如果不指定就是默认单个释放
Semaphore实现的功能就类似厕所有5个坑,假如有10个人要上厕所,那么同时只能有多少个人去上厕所呢?同时只能有5个人能够占用,当5个人中 的任何一个人让开后,其中等待的另外5个人中又有一个人可以占用了。另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Semaphore对象时传入的参数选项。单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。Semaphore在实现这种排队机制的时候很优秀,代码简洁
Semaphore维护了当前访问的个数,提供同步机制,控制同时访问的个数。在数据结构中链表可以保存“无限”的节点,用Semaphore可以实现有限大小的链表。另外重入锁 ReentrantLock 也可以实现该功能,但实现上要复杂些。
Semaphore分为单值和多值两种:
1、单值的Semaphore管理的信号量只有1个,该信号量只能被1个,只能被一个线程所获得,意味着并发的代码只能被一个线程运行,这就相当于是一个互斥锁了
2、多值的Semaphore管理的信号量多余1个,主要用于控制并发数
看一下代码例子:
public static void main(String[] args)
{
final Semaphore semaphore = new Semaphore(5); Runnable runnable = new Runnable()
{
public void run()
{
try
{
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "获得了信号量,时间为" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + "释放了信号量,时间为" + System.currentTimeMillis());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
semaphore.release();
}
}
}; Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++)
threads[i] = new Thread(runnable);
for (int i = 0; i < threads.length; i++)
threads[i].start();
}
看一下运行结果:
1 Thread-1获得了信号量,时间为1444557040464
2 Thread-2获得了信号量,时间为1444557040465
3 Thread-0获得了信号量,时间为1444557040464
4 Thread-3获得了信号量,时间为1444557040465
5 Thread-4获得了信号量,时间为1444557040465
6 Thread-2释放了信号量,时间为1444557042466
7 Thread-4释放了信号量,时间为1444557042466
8 Thread-0释放了信号量,时间为1444557042466
9 Thread-1释放了信号量,时间为1444557042466
10 Thread-3释放了信号量,时间为1444557042466
11 Thread-9获得了信号量,时间为1444557042467
12 Thread-7获得了信号量,时间为1444557042466
13 Thread-6获得了信号量,时间为1444557042466
14 Thread-5获得了信号量,时间为1444557042466
15 Thread-8获得了信号量,时间为1444557042467
16 Thread-9释放了信号量,时间为1444557044467
17 Thread-6释放了信号量,时间为1444557044467
18 Thread-7释放了信号量,时间为1444557044467
19 Thread-5释放了信号量,时间为1444557044468
20 Thread-8释放了信号量,时间为1444557044468
前10行为一部分,运行的线程是1 2 0 3 4,看到时间差也都是代码约定的2秒;后10行为一部分,运行的线程是9 7 6 5 8,时间差也都是约定的2秒,这就体现出了Semaphore的作用了,这里由于是在中间使用sleep ,所以看起来是有序的,必须释放5个才能获取,其实不然,是一个释放,信号量发现还有空余的就会立刻分给下一个等待的线程。
这种通过Semaphore控制并发并发数的方式和通过控制线程数来控制并发数的方式相比,粒度更小,因为Semaphore可以通过acquire方法和release方法来控制代码块的并发数。
最后注意两点:
1、Semaphore可以指定公平锁还是非公平锁
2、acquire方法和release方法是可以有参数的,表示获取/返还的信号量个数
java 多线程 28 : 多线程组件之 Semaphore 信号量的更多相关文章
- Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例
概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 ...
- java架构之路(多线程)JUC并发编程之Semaphore信号量、CountDownLatch、CyclicBarrier栅栏、Executors线程池
上期回顾: 上次博客我们主要说了我们juc并发包下面的ReetrantLock的一些简单使用和底层的原理,是如何实现公平锁.非公平锁的.内部的双向链表到底是什么意思,prev和next到底是什么,为什 ...
- 多线程锁:Mutex互斥体,Semaphore信号量,Monitor监视器,lock,原子操作InterLocked
Mutex类 “mutex”是术语“互相排斥(mutually exclusive)”的简写形式,也就是互斥量.互斥量跟临界区中提到的Monitor很相似,只有拥有互斥对象的线程才具有访问资源的权限, ...
- Java多线程同步工具类之Semaphore
Semaphore信号量通常做为控制线程并发个数的工具来使用,它可以用来限制同时并发访问资源的线程个数. 一.Semaphore使用 下面我们通过一个简单的例子来看下Semaphore的具体使用,我们 ...
- java并发与多线程面试题与问题集合
http://www.importnew.com/12773.html https://blog.csdn.net/u011163372/article/details/73995897 ...
- [Java][读书笔记]多线程编程
前言:最近复习java,发现一本很好的资料,<Java2参考大全 (第五版)> Herbert.Schildt.书比较老了,06年的,一些 ...
- Java中使用多线程、curl及代理IP模拟post提交和get访问
Java中使用多线程.curl及代理IP模拟post提交和get访问 菜鸟,多线程好玩就写着玩,大神可以路过指教,小弟在这受教,谢谢! 更多分享请关注微信公众号:lvxing1788 ~~~~~~ 分 ...
- Java中的 多线程编程
Java 中的多线程编程 一.多线程的优缺点 多线程的优点: 1)资源利用率更好2)程序设计在某些情况下更简单3)程序响应更快 多线程的代价: 1)设计更复杂虽然有一些多线程应用程序比单线程的应用程序 ...
- Java中使用多线程、curl及代理IP模拟post提交和get訪问
Java中使用多线程.curl及代理IP模拟post提交和get訪问 菜鸟,多线程好玩就写着玩.大神能够路过不吝赐教.小弟在这受教.谢谢! 很多其它分享请关注微信公众号:lvxing1788 ~~~~ ...
随机推荐
- iOS 对 HTTPS 证书链的验证
HTTPS从最终的数据解析的角度,与HTTP相同.HTTPS将HTTP协议数据包放到SSL/TSL层加密后,在TCP/IP层组成IP数据报去传输,以此保证传输数据的安全:而对于接收端,在SSL/TSL ...
- Socket编程:之TCP案例
转载请加上博文引用:http://i.cnblogs.com/EditPosts.aspx?postid=5733248&update=1 服务端: #include <stdio.h& ...
- io分析神器blktrace
一.概述 [许久之前就用过blktrace,现整理如下] 从linux 一个完整的IO入手分析: 一个I/O请求进入block layer之后,可能会经历下面的过程: Remap: 可能被DM(Dev ...
- Spark弹性分布式数据集RDD
RDD(Resilient Distributed Dataset)是Spark的最基本抽象,是对分布式内存的抽象使用,实现了以操作本地集合的方式来操作分布式数据集的抽象实现.RDD是Spark最核心 ...
- linux文件系统 - 初始化(三)
执行init程序 一.目的 内核加载完initrd文件后,为挂载磁盘文件系统做好了必要的准备工作,包括挂载了sysfs.proc文件系统,加载了磁盘驱动程序驱动程序等.接下来,内核跳转到用户空间的in ...
- 跟我学SharePoint 2013视频培训课程——理解SharePoint网站的体系结构(3)
课程简介 第三天,理解SharePoint 2013 网站的体系结构 视频 SharePoint 2013 交流群 41032413
- SharePoint 2010、2013多个域之间互信(Domain Trust)的设计与实施
在现实的业务场景中,有时为了更好的管理域用户和服务.我们往往会创建多个分散式的域,每个域的Administrator专注于维护特定域中的用户和资源,Administrator也可以定义安全策略,比如账 ...
- asp.net中C#中计算时间差代码
我用的最简单的办法是 代码如下 复制代码 DateTime dtone = Convert.ToDateTime("2007-1-1 05:32:22");DateTime dtw ...
- AR模型与数据平稳性之间的关系
作者:桂. 时间:2017-12-19 21:39:08 链接:http://www.cnblogs.com/xingshansi/p/8068021.html 前言 前几天碰到一个序列分析的问题, ...
- nginx增加ssl支持 - 编译时参数详情列表
./configure \ --with-http_ssl_module \ make && make install nginx编译参数说明如下: --prefix=&l ...