1. Semaphore是非常有用的一个多线程并发控制组件(Java还有CountDownLatch、CyclicBarrier、Exchanger多线程组件),它相当于是一个并发控制器,是用于管理信号量的。构造的时候传入可供管理的信号量的数值,这个数值就是控制并发数量的,就是同时能几个线程访问。我们需要控制并发的代码,执行前先通过acquire方法获取信号,执行后通过release归还信号 。每次acquire返回成功后,Semaphore可用的信号量就会减少一个,如果没有可用的信号,acquire调用就会阻塞,等待有release调用释放信号后,acquire才会得到信号并返回。

    private Semaphore semaphore = new Semaphore(3, true); #true时,使用公平策略,也就是是使用公平锁

    ps:注意这里信号量acquire方法和release方法是可以有参数的,表示获取/返还的信号量个数,如果不指定就是默认单个释放。

  2. Semaphore分为单值和多值两种

    • 单值的Semaphore管理的信号量只有1个,该信号量只能被1个,只能被一个线程所获得,意味着并发的代码只能被一个线程运行,这就相当于是一个互斥锁了。
    • 多值的Semaphore管理的信号量多余1个,主要用于控制并发数。
  3. 这种通过Semaphore控制并发并发数的方式和通过控制线程数来控制并发数的方式相比,粒度更小,因为Semaphore可以通过acquire方法和release方法来控制代码块的并发数。

  4. 在构造Semaphore对象时,同时可以控制并发时抢占锁的公平策略。在公平的锁上,线程按照他们发出请求的顺序获取锁,但在非公平锁上,则允许‘插队’:当一个线程请求非公平锁时,如果在发出请求的同时该锁变成可用状态,那么这个线程会跳过队列中所有的等待线程而获得锁。

  5. 非公平锁的效率高于公平锁,主要原因是,在恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟。

    ps.当持有锁的时间相对较长,应该使用公平锁。在这些情况下,插队带来的吞吐量提升可能不会出现。

  6. 使用示例,模仿上厕所排队的例子

 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();
}
}

Java核心-多线程-并发控制器-Semaphore信号量的更多相关文章

  1. Java核心-多线程-并发控制器-CyclicBarrier同步屏障

    1.基本概念 中文译本同步屏障,同样来自jdk并发工具包中一个并发控制器,它的使用和CountDownLatch有点相似,能够完成某些相同并发场景,但是它们却不相同. 2.抽象模型 主要用来实现多个线 ...

  2. Java核心-多线程-并发控制器-CountDownLatch倒数闩

    1.基本概念 CountDownLatch,中文名倒数闩,jdk并发工具包中一个并发控制器,它抽象了一个常见的多线程并发场景,开发人员使用它可以写出同时兼顾线程安全性与高效率的代码. 2.抽象模型 相 ...

  3. Java核心-多线程-并发控制器-Exchanger交换器

    1.基本概念 Exchanger,从名字上理解就是交换.Exchanger用于在两个线程之间进行数据交换,注意也只能在两个线程之间进行数据交换. 线程会阻塞在Exchanger的exchange方法上 ...

  4. java核心-多线程(1)-知识大纲

    Thread,整理一份多线程知识大纲,大写意 1.概念介绍 线程 进程 并发 2.基础知识介绍 Java线程类 Thread 静态方法&实例方法 Runnable Callable Futur ...

  5. Java接口多线程并发测试 (一)

    本文为作者原创,禁止转载,违者必究法律责任!!! 本文为作者原创,禁止转载,违者必究法律责任!!! Java接口多线程并发测试 一,首先写一个接口post 请求代码: import org.apach ...

  6. Java多线程并发工具类-信号量Semaphore对象讲解

    Java多线程并发工具类-Semaphore对象讲解 通过前面的学习,我们已经知道了Java多线程并发场景中使用比较多的两个工具类:做加法的CycliBarrier对象以及做减法的CountDownL ...

  7. java 多线程 28 : 多线程组件之 Semaphore 信号量

    Semaphore是非常有用的一个组件,它相当于是一个并发控制器,是用于管理信号量的.构造的时候传入可供管理的信号量的数值,这个数值就是控制并发数量的,就是同时能几个线程访问.我们需要控制并发的代码, ...

  8. java核心-多线程-Java多线程编程涉及到包、类

    Java有关多线程编程设计的类主要涉及两个包java.lang和java.util.concurrent两个包 java.lang包,主要是线程基础类 <1>Thread <2> ...

  9. java核心-多线程(8)- 并发原子类

        使用锁能解决并发时线程安全性,但锁的代价比较大,而且降低性能.有些时候可以使用原子类(juc-atomic包中的原子类).还有一些其他的非加锁式并发处理方式,我写这篇文章来源于Java中有哪些 ...

随机推荐

  1. 三,用户交互方式与python基本数据类型

    一.与用户交互 input python2中:用户输入什么类型的数据,就储存为什么类型的数据.比如输入数字则储存为整型,输入符号则存储为字符串型.raw_input会将所有输入的类型转换为字符串型. ...

  2. 2018—自学Selenium+Python 笔记(一)

    在开始学习前,先唠几句: 身为一个开发人员,为何想要转测试..很多人不解. 但我觉得这并没有什么不可,测试人员是质量的把控者: 要出一个让客户满意的产品,单纯靠开发自测,是不够的..相信其中缘由大家都 ...

  3. git教程:工作区和暂存区

    Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念. 先来看名词解释. 工作区(Working Directory) 就是你在电脑里能看到的目录,比如我的learngit文件夹就是一个工 ...

  4. Find Longest common string

    动态规划法: 用二维矩阵来的每个元素来代表两个字符串的字符匹配情况, LCS[i, j]= LCS[i-1, j-1] + 1  , if X[i-1] == Y[J-1]. LCS[i, j] =0 ...

  5. swagger2常用注解

    常用注解: @Api()用于类: 表示标识这个类是swagger的资源 @ApiOperation()用于方法: 表示一个http请求的操作 @ApiParam()用于方法,参数,字段说明: 表示对参 ...

  6. ubuntu下使用opencv问题以及解决方案

    CMakeFiles/hw5_1_node.dir/computeORB.o: In function `cv::String::~String()':/usr/local/include/openc ...

  7. vue中使用video插件vue-video-player

    一.安装插件 npm install vue-video-player --save 二.配置插件 在main.js中全局配置插件 import VideoPlayer from 'vue-video ...

  8. USB接口禁用与启用

    前几天闺蜜淘了一台小本,但是发现计算机USB接口是禁用的,有点头疼,所以问了万能的度娘,找到了n种办法.不过这一种是适用于我的情况,简单记录一下. 解决方法:(主要就是修改注册表) 1.打开注册表编辑 ...

  9. C++中的基础特性:封装,继承,多态

    抽象: 要将现实中的一个具体事务,变成C++中的一个类,例如将现实中的汽车变成代码中的car类.完成这个过程就需要 抽象 这一基本手段. 抽象是指 对具体问题(对象)进行分析概括,找出该类对象的公共性 ...

  10. Win10激活密钥key(可激活所有版本)

    Win10激活密钥key(可激活所有版本) Win10一年的免费升级服务已经到期,用户要使用Win10系统,就需要最新Win10密钥来激活Win10,一般激活Win10系统有两种方式,一个是使用Win ...