Java核心-多线程-并发控制器-Semaphore信号量
Semaphore是非常有用的一个多线程并发控制组件(Java还有CountDownLatch、CyclicBarrier、Exchanger多线程组件),它相当于是一个并发控制器,是用于管理信号量的。构造的时候传入可供管理的信号量的数值,这个数值就是控制并发数量的,就是同时能几个线程访问。我们需要控制并发的代码,执行前先通过acquire方法获取信号,执行后通过release归还信号 。每次acquire返回成功后,Semaphore可用的信号量就会减少一个,如果没有可用的信号,acquire调用就会阻塞,等待有release调用释放信号后,acquire才会得到信号并返回。
private Semaphore semaphore = new Semaphore(3, true); #true时,使用公平策略,也就是是使用公平锁
ps:注意这里信号量acquire方法和release方法是可以有参数的,表示获取/返还的信号量个数,如果不指定就是默认单个释放。Semaphore分为单值和多值两种
- 单值的Semaphore管理的信号量只有1个,该信号量只能被1个,只能被一个线程所获得,意味着并发的代码只能被一个线程运行,这就相当于是一个互斥锁了。
- 多值的Semaphore管理的信号量多余1个,主要用于控制并发数。
这种通过Semaphore控制并发并发数的方式和通过控制线程数来控制并发数的方式相比,粒度更小,因为Semaphore可以通过acquire方法和release方法来控制代码块的并发数。
在构造Semaphore对象时,同时可以控制并发时抢占锁的公平策略。在公平的锁上,线程按照他们发出请求的顺序获取锁,但在非公平锁上,则允许‘插队’:当一个线程请求非公平锁时,如果在发出请求的同时该锁变成可用状态,那么这个线程会跳过队列中所有的等待线程而获得锁。
非公平锁的效率高于公平锁,主要原因是,在恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟。
ps.当持有锁的时间相对较长,应该使用公平锁。在这些情况下,插队带来的吞吐量提升可能不会出现。使用示例,模仿上厕所排队的例子
package common_test;
import java.util.Random;
import java.util.concurrent.*;
public class SemaphoreTest {
private Semaphore semaphore = new Semaphore(3, true);
private Random random = new Random();
class Task implements Runnable{
private String id;
public Task(String id){
this.id = id;
}
public void run() {
try {
semaphore.acquire();
System.out.println("茅坑" + id + " 被占用了");
work();
System.out.println("茅坑" + id + " 空了");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
semaphore.release();
}
}
public void work(){
int worktime = random.nextInt(1000);
System.out.println("茅坑 " + id + "使用了"+ worktime + "秒");
try {
Thread.sleep(worktime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SemaphoreTest semaphoreTest = new SemaphoreTest();
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
newCachedThreadPool.submit(semaphoreTest.new Task(1+""));
newCachedThreadPool.submit(semaphoreTest.new Task(2+""));
newCachedThreadPool.submit(semaphoreTest.new Task(3+""));
newCachedThreadPool.submit(semaphoreTest.new Task(4+""));
newCachedThreadPool.submit(semaphoreTest.new Task(5+""));
newCachedThreadPool.submit(semaphoreTest.new Task(6+""));
newCachedThreadPool.submit(semaphoreTest.new Task(7+""));
newCachedThreadPool.shutdown();
}
}
最新文章
- 转:IT公司的十大内耗,别说你公司没有!
- SQL SERVER 属性OWNER不可用于数据库xxx。该对象可能没有此属性,也可能是访问权限不足而无法检索。
- 2013年最新流行的响应式 WordPress 主题【下篇】
- Ubuntu中root用户和user用户的相互切换
- No.005 Longest Palindromic Substring
- 跨线程调用控件之MethodInvoker
- delphi 选中的展开0级 子级不展开
- 关于position和float的用法!
- ASP.NET Zero--11.一个例子(4)商品分类管理-数据检验
- 【转载】JAVA中综合接口和抽象类实现的一种“抽象接口”
- Jdk 接口类RandomAccess了解
- RMQ 字符串 F. Strings and Queries
- 机器学习&;深度学习基础(机器学习基础的算法概述及代码)
- IPC 之 Binder 初识
- 【工具类】怎么进入阿里云docker仓库
- MySQL 内存和CPU优化相关的参数
- python struct模块的使用
- cogs1885 [WC2006]水管局长数据加强版
- 12 并发编程-(线程)-线程queue&;进程池与线程池
- EXT.NET各个版本下载地址
热门文章
- [C# 基础知识系列]专题二:委托的本质论 (转载)
- 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contai
- Checked Exceptions
- Linux报错之ping: www.baidu.com: Name or service not known
- linux下centos解压时报错: gzip: stdin: not in gzip format tar: Child returned status 1 tar: Error is not recoverable: exiting now
- 《XX重大技术需求征集系统》的可用性和可修改性战术分析
- 解题报告 『[USACO08NOV]Mixed Up Cows(状压动规)』
- H3C_IRF
- usg6000
- C++ operator 学习