JAVA多线程提高九:Semaphere同步工具
java 中Semaphere可类比操作系统信号量,硬件资源如IO、内存、磁盘等都是有固定量的,多个程序需要竞争这些资源,没有资源就需要被挂起。
一、类和方法摘要
构造函数:
public Semaphore(int permits):创建具有给定的许可数和非公平的公平设置的 Semaphore。
-参数 :
permits - 初始的可用许可数目。此值可能为负数,在这种情况下,必须在授予任何获取前进行释放。
public Semaphore(int permits, boolean fair):创建具有给定的许可数和给定的公平设置的 Semaphore。
-参数:
permits - 初始的可用许可数目。此值可能为负数,在这种情况下,必须在授予任何获取前进行释放。
fair - 如果此信号量保证在争用时按先进先出的顺序授予许可,则为 true;否则为 false。
常用方法:
void acquire():从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
void release():释放一个许可,将其返回给信号量。
int availablePermits():返回此信号量中当前可用的许可数。
boolean hasQueuedThreads():查询是否有线程正在等待获取。
二、使用技巧
将信号量初始化为 1,使得它在使用时最多只有一个可用的许可,从而可用作一个相互排斥的锁。这通常也称为二进制信号量,因为它只能有两种状态:一个可用的许可,或零个可用的许可。按此方式使用时,二进制信号量具有某种属性(与很多 Lock 实现不同),即可以由线程释放“锁”,而不是由所有者(因为信号量没有所有权的概念)。在某些专门的上下文(如死锁恢复)中这会很有用。
三、对比线程池
线程池控制的是线程数量,而信号量控制的是并发数量,虽然说看起来一样,但两者还是有区别的。
信号量类似于锁机制,信号量的调用,当达到数量后,线程还是存在的,只是被挂起了而已。而线程池,同时执行的线程数量是固定的,超过了数量的只能等待。
代码示例:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore; public class SemaphoreTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final Semaphore sp = new Semaphore(3);
for(int i=0;i<10;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
sp.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"进入,当前已有" + (3-sp.availablePermits()) + "个并发");
try {
Thread.sleep((long)(Math.random()*10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"即将离开");
sp.release();
//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
System.out.println("线程" + Thread.currentThread().getName() +
"已离开,当前已有" + (3-sp.availablePermits()) + "个并发");
}
};
service.execute(runnable);
}
} }
输出:
线程pool-1-thread-1进入,当前已有3个并发
线程pool-1-thread-3进入,当前已有3个并发
线程pool-1-thread-2进入,当前已有3个并发
线程pool-1-thread-1即将离开
线程pool-1-thread-1已离开,当前已有2个并发
线程pool-1-thread-4进入,当前已有3个并发
线程pool-1-thread-3即将离开
线程pool-1-thread-3已离开,当前已有2个并发
线程pool-1-thread-5进入,当前已有3个并发
线程pool-1-thread-4即将离开
线程pool-1-thread-4已离开,当前已有2个并发
线程pool-1-thread-6进入,当前已有3个并发
线程pool-1-thread-2即将离开
线程pool-1-thread-2已离开,当前已有2个并发
线程pool-1-thread-7进入,当前已有3个并发
线程pool-1-thread-7即将离开
线程pool-1-thread-7已离开,当前已有2个并发
线程pool-1-thread-8进入,当前已有3个并发
线程pool-1-thread-5即将离开
线程pool-1-thread-5已离开,当前已有3个并发
线程pool-1-thread-9进入,当前已有3个并发
线程pool-1-thread-6即将离开
线程pool-1-thread-6已离开,当前已有2个并发
线程pool-1-thread-10进入,当前已有3个并发
线程pool-1-thread-8即将离开
线程pool-1-thread-8已离开,当前已有2个并发
线程pool-1-thread-10即将离开
线程pool-1-thread-10已离开,当前已有1个并发
线程pool-1-thread-9即将离开
线程pool-1-thread-9已离开,当前已有0个并发
可以同时有3个线程执行sp.acquire()到sp.release()之间的代码。
参考资料:
<<Java多线程与并发库高级应用>> 张孝祥 视频
JAVA多线程提高九:Semaphere同步工具的更多相关文章
- JAVA多线程提高十四:同步工具Exchanger
Exchanger可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchange 方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象.Exchanger 可能被视 ...
- java多线程系列9 高级同步工具(3) CyclicBarrier
CyclicBarrier 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point) 然后一再执行 public class CyclicBar ...
- java多线程系列7 高级同步工具(1)信号量Semaphore
Semaphore叫做信号量 可以控制某个资源可被同时访问的个数, acquire() 获取一个许可,得到许可才能执行后面的代码,如果没有就等待. release() 释放一个许可. 当信号量的只允许 ...
- java多线程系列8 高级同步工具(2)CountDownLatch
CountDownLatch,计数器的初始值为线程的数量.每当一个线程完成了自己的任务后, 计数器的值就会减1.当计数器值到达0时,它表示所有的线程已经完成了任务, 然后在闭锁上等待的线程就可以恢复执 ...
- java多线程系列(九)---ArrayBlockingQueue源码分析
java多线程系列(九)---ArrayBlockingQueue源码分析 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 j ...
- Java多线程之线程的同步
Java多线程之线程的同步 实际开发中我们也经常提到说线程安全问题,那么什么是线程安全问题呢? 线程不安全就是说在多线程编程中出现了错误情况,由于系统的线程调度具有一定的随机性,当使用多个线程来访问同 ...
- Java多线程——线程之间的同步
Java多线程——线程之间的同步 摘要:本文主要学习多线程之间是如何同步的,如何使用volatile关键字,如何使用synchronized修饰的同步代码块和同步方法解决线程安全问题. 部分内容来自以 ...
- JAVA多线程提高十:同步工具CyclicBarrier与CountDownLatch
今天继续学习其它的同步工具:CyclicBarrier与CountDownLatch 一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公 ...
- Java多线程编程(4)--线程同步机制
一.锁 1.锁的概念 线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题.锁 ...
随机推荐
- 基础系列(1)—— NET框架及C#语言
一.在.NET之前的编程世界 C#语言是在微软公司的.NET框架上开发程序而设计的,首先作者给大家纠正了一下C#的正确发音:See Sharp (一) 20世纪90年代末的Windows编程 这时大多 ...
- 软工1816 · Alpha冲刺(5/10)
团队信息 队名:爸爸饿了 组长博客:here 作业博客:here 组员情况 组员1(组长):王彬 过去两天完成了哪些任务 后端代码复审 福大各个食堂的菜品口味量化.属性标记 组织前后端线下协作 接下来 ...
- 《我是IT小小鸟》读后感
<我是IT小小鸟>读后感 说实话,我根本不喜欢看这本书,要不是因为老师要求我也不会去看的,其实当老师提起这本书的时候我还是有点兴趣,去看的,可是看了很多后,觉得这根本不适合我,里面说的都是 ...
- 0429团队项目-Scrum团队成立
Scrum团队成立 团队名称:开拓者 团队目标:努力让每一个小伙伴在学会走路的基础上学会跑. 团队口号:我们要的只是这片天而已. 团队照:正面照+背影照(那就是为什么组名叫开拓者) 5.2 角色分配 ...
- 微信小程序组件 自定义单选
<view class='userperson'> <view class='f30 flexca'>请选择您的注册身份</view> <view class ...
- 微信小程序 功能函数 地图定位相对直线距离
GetDistance:function(lat1, lng1, lat2, lng2){ // console.log(lat1) var radLat1 = lat1 * Math.PI / ...
- 在linux下编译线程程序undefined reference to `pthread_create'
由于是Linux新手,所以现在才开始接触线程编程,照着GUN/Linux编程指南中的一个例子输入编译,结果出现如下错误:undefined reference to 'pthread_create'u ...
- mysql中用户和权限
用户管理 用户数据所在位置: mysql中的所有用户,都存储在系统数据库(mysql)中的user 表中——不管哪个数据库的用户,都存储在这里. 表初始内容如下: 创建用户: 形式: create ...
- 第103天:CSS3中Flex布局(伸缩布局)详解
一.Flex布局 Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性. 任何一个容器都可以指定为Flex布局. .box{ display: flex; } 行 ...
- 学习websocket-SignalR,MVC中使用SignalR打造酷炫实用的即时通讯
http://www.cnblogs.com/Leo_wl/p/4793284.html http://www.fangsi.net/archives/1144.html