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 - 1618 Weak Key(RMQ算法)
题目: 给出k个互不相同的证书组成的序列Ni,判断是否存在4个证书Np.Nq.Nr.Ns(1≤p<q<r<s≤k)使得Nq>Ns>Np>Nr或者Nq<Ns&l ...
- js的title提示
$(function() { //先在页面创建一个层 var jqtip = $("<div id='jqtip20130719'" + "style='paddi ...
- MyBatis 中 resultMap 详解
resultMap 是 Mybatis 最强大的元素之一,它可以将查询到的复杂数据(比如查询到几个表中数据)映射到一个结果集当中.如在实际应用中,有一个表为(用户角色表),通过查询用户表信息展示页面, ...
- Linux之iptables(六、rich规则)
其它规则 当基本firewalld语法规则不能满足要求时,可以使用以下更复杂的规则 rich-rules 富规则,功能强,表达性语言 Direct configuration rules 直接规则,灵 ...
- 简述systemd的新特性及unit常见类型分析、使用systemd管理编译安装的nginx
1. systemd新特性 并行处理(同时启动)所有服务. 基于依赖关系定义的服务控制逻辑 系统状态快照 按需激活进程,只有第一次被访问时才会真正启动: 2. systemd的常见unit类型 Ser ...
- 67.基于nested object实现博客与评论嵌套关系
1.做一个实验,引出来为什么需要nested object 冗余数据方式的来建模,其实用的就是object类型,我们这里又要引入一种新的object类型,nested object类型 博客,评论,做 ...
- php利用32进制实现对id加密解密
前言 最近在项目中遇到一个问题,当前用户分享一个邀请码给好友,好友根据邀请码注册成为新用户之后,则成为当前用户的下级,特定条件下,可以得到下级用户的一系列返利.这里要实现的就是根据当前用户的id,生成 ...
- PYGAME学习笔记_01
01_使用PYGAME创建图形窗口 1.1_游戏的初始化和退出 pygame.init() 写入并初始化所有PYGAME模块,使用其他模块之前,必须先调用init方法 pygame.quit() 卸载 ...
- 洛谷 2055 BZOJ 1433 [ZJOI2009]假期的宿舍
[题解] 既然是一人对应一床,那么显然可以用二分图匹配来做.俩人认识的话,如果其中一个a是在校学生,另一个b不回家,b就可以向a的床连边(a,b当然也可以是同一个人). 然后如果最大匹配数大于等于需要 ...
- 【Codeforces 923A】Primal Sport
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 考虑怎么得到数字x2=N,假设是质数p的倍数 那么x1肯定在x2-p+1~x2这个范围内才行 因为p的倍数要刚好大于等于x1, 所以x1肯定是 ...