Java并发编程系列之Semaphore详解
简单介绍
我们以饭店为例,假设饭店只有三个座位,一开始三个座位都是空的。这时如果同时来了三个客人,服务员人允许他们进去用餐,然后对外说暂无座位。后来的客人必须在门口等待,直到有客人离开。这时,如果有一个客人离开,服务员告诉客人,可以进来用餐,如果又有客人离开,则又可以进来客人用餐,如此往复。
在这个饭店中,座位是公共资源,每个人好比一个线程,服务员起的就是信号量的作用。信号量是一个非负整数,表示了当前公共资源的可用数目(在上面的例子中可以用空闲的座位类比信号量),当一个线程要使用公共资源时(在上面的例子中可以用客人比线程),首先要查看信号量,如果信号量的值大于1,则将其减1,然后去占有公共资源。如果信号量的值为0,则线程会将自己阻塞,直到有其它线程释放公共资源。
1、简单介绍Semaphore
a、可用来控制同时访问特定资源的线程数量,以此来达到协调线程工作。
b、维护了一个虚拟的资源池,如果许可为0则线程阻塞等待,直到许可大于0时又可以有机会获取许可了。
c、 内部也有公平锁、非公平锁来访问资源的静态内部类。
2、Semaphore方法
a、public Semaphore(int permits);// 创建一个给定许可数量的信号量对象,且默认以非公平锁方式获取资源
b、public Semaphore(int permits, boolean fair);//创建一个给定许可数量的信号量对象,且是否公平方式由传入的fair布尔参数值决定
c、public void acquire() ;//从此信号量获取一个许可,当许可数量小于零时,则阻塞等待
d、public void acquire(int permits) ;//从此信号量获取permits个许可,当许可数量小于零时,则阻塞等待,但是当阻塞等待的线程被唤醒后发现被中断过的话则会抛InterruptedException异常
e、public void acquireUninterruptibly(int permits) ;从此信号量获取permits个许可,当许可数量小于零时,则阻塞等待,但是当阻塞等待的线程被唤醒后发现被中断过的话则不会抛InterruptedException异常
f、public void release();//释放一个许可
g、public void release(int permits);释放permits个许可
以上只是列出主要方法名,方法详细解释,Semaphore类上面都有注释。就不一一累出来了。
举一个简单例子,帮助我们加深印象
/**
* @author shuliangzhao
* @Title: SemaPhoreTest
* @ProjectName design-parent
* @Description: TODO
* @date 2019/6/5 22:50
*/
public class SemaPhoreTest {
private Semaphore semaphore = new Semaphore(3);
class TaskThread implements Runnable{
private int id;
public TaskThread(int id) {
this.id = id;
}
@Override
public void run() {
try {
semaphore.acquire();
System.out.println("Thread " + id + " is working");
Thread.sleep(2000);
semaphore.release();
System.out.println("Thread " + id + " is over");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SemaPhoreTest semaPhoreTest = new SemaPhoreTest();
/*for (int i = 0;i<6;i++) {
Thread thread = new Thread(semaPhoreTest.new TaskThread(i));
thread.start();
}*/
ExecutorService executorService = Executors.newCachedThreadPool();//同步队列线程
executorService.submit(semaPhoreTest.new TaskThread(1));
executorService.submit(semaPhoreTest.new TaskThread(2));
executorService.submit(semaPhoreTest.new TaskThread(3));
executorService.submit(semaPhoreTest.new TaskThread(4));
executorService.submit(semaPhoreTest.new TaskThread(5));
executorService.submit(semaPhoreTest.new TaskThread(6));
executorService.submit(semaPhoreTest.new TaskThread(7));
executorService.shutdown();
}
}
运行结果

Java并发编程系列之Semaphore详解的更多相关文章
- Java并发编程系列之CyclicBarrier详解
简介 jdk原文 A synchronization aid that allows a set of threads to all wait for each other to reach a co ...
- Java并发编程1--synchronized关键字用法详解
1.synchronized的作用 首先synchronized可以修饰方法或代码块,可以保证同一时刻只有一个线程可以执行这个方法或代码块,从而达到同步的效果,同时可以保证共享变量的内存可见性 2.s ...
- java并发编程系列原理篇--JDK中的通信工具类Semaphore
前言 java多线程之间进行通信时,JDK主要提供了以下几种通信工具类.主要有Semaphore.CountDownLatch.CyclicBarrier.exchanger.Phaser这几个通讯类 ...
- Java并发编程系列-(2) 线程的并发工具类
2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了 ...
- Java并发编程系列-(4) 显式锁与AQS
4 显示锁和AQS 4.1 Lock接口 核心方法 Java在java.util.concurrent.locks包中提供了一系列的显示锁类,其中最基础的就是Lock接口,该接口提供了几个常见的锁相关 ...
- Java并发编程系列-(8) JMM和底层实现原理
8. JMM和底层实现原理 8.1 线程间的通信与同步 线程之间的通信 线程的通信是指线程之间以何种机制来交换信息.在编程中,线程之间的通信机制有两种,共享内存和消息传递. 在共享内存的并发模型里,线 ...
- 【原创】Java并发编程系列1:大纲
[原创]Java并发编程系列1:大纲 一个人能力当中所蕴藏的潜能,远超过自己想象以外. 为什么要学习并发编程 随着现今互联网行业的迅猛发展,其业务复杂度.并发量也在不断增加,对程序的要求变得越来越高, ...
- 干货:Java并发编程系列之volatile(二)
接上一篇<Java并发编程系列之synchronized(一)>,这是第二篇,说的是关于并发编程的volatile元素. Java语言规范第三版中对volatile的定义如下:Java编程 ...
- Java并发编程系列-(5) Java并发容器
5 并发容器 5.1 Hashtable.HashMap.TreeMap.HashSet.LinkedHashMap 在介绍并发容器之前,先分析下普通的容器,以及相应的实现,方便后续的对比. Hash ...
随机推荐
- UVA - 10048 Audiophobia(Floyd求路径上最大值的最小)
题目&分析: 思路: Floyd变形(见上述紫书分析),根据题目要求对应的改变判断条件来解题. 代码: #include <bits/stdc++.h> #define inf 0 ...
- application对象的使用
application对象的使用 制作人:全心全意 application对象用于保存所有应用程序中的公有数据.它在服务器启动时自动创建,在服务器停止时销毁.当application对象没有被销毁时, ...
- 洛谷 4768 LOJ 2718「NOI2018」归程
[题解] 本题有多种做法,例如可持久化并查集.kruskal重构树等. kruskal重构树的做法是这样的:先把边按照海拔h从大到小的顺序排序,然后跑kruskal建立海拔的最大生成树,顺便建krus ...
- spark之scala快速入门
scala和java都是在jvm之上的语言,相对来讲,scala热度比较低,其实并不是一个特别好的语言选择. 原因倒不是因为scala本身的缺点,而是使用人群不够多,论坛和社区不够活跃.这就跟社交软件 ...
- 《Spring in action》之高级装配
1.Spring 通过配置profile bean.激活profile来设置对应环境. 配置profile bean: 可通过@Profile("dev")注解进行配置.也可以通过 ...
- ADO连接ACCESS2007及以上版本的数据库
function getaccessstr(databasename:string;password:string;accessVer:string='access2003'):string; beg ...
- MVC之查询demo
上篇已经说过怎样建立MVC项目.这次主要讲述样例的实现. 其基本的功能就是从数据库中查询一些基本信息. 前边我们已经将实体引入到了项目中,这时Model目录中已经出现了我们建立的newsSystem. ...
- Windows 注册表常用操作
1 添加一个主键(比如在HKEY_LOCAL_MACHINE\SOFTWARE\中添加一个ABCEDFGHIJKLMN主键) Windows Registry Editor Version 5.00 ...
- Android中apk动态载入技术研究(2)android插件化及实现
了解了android中类载入的前期知识点后,来看看android中DexClassLoader详细的实现 详细载入流程例如以下: 宿主程序会到文件系统比方SD卡中去载入APK[1],然 ...
- J2EE基础总结(5)——EJB
什么是EJB JB事实上就是企业Java Beans. EJB是J2EE平台的重要组成部分. J2EE平台基于组件的企业级应用架构,提供多 层次.分布式和高事务的功能特点. EJB提供 ...