java并发编程专题(六)----浅析(JUC)Semaphore
作者:rickiyang 发布时间:2023-07-27 23:30:28
半路开始看的朋友可以回顾一下前几篇
java并发编程专题(一)----线程基础知识
java并发编程专题(二)----如何创建并运行java线程
java并发编程专题(三)----详解线程的同步
java并发编程专题(四)----浅谈(JUC)Lock锁
java并发编程专题(五)----详解(JUC)ReentrantLock
Semaphore,从字面意义上我们知道他是信号量的意思。在java中,一个计数信号量维护了一个许可集。Semaphore 只对可用许可的号码进行计数,并采取相应的行动。拿到信号量的线程可以进入代码,否则就等待。通过acquire()和release()获取和释放访问许可。
信号量Semaphore是一个控制访问多个共享资源的计数器,它本质上是一个“共享锁”。
Java并发提供了两种加锁模式:共享锁和独占锁。前面介绍的ReentrantLock就是独占锁。对于独占锁而言,它每次只能有一个线程持有,而共享锁则不同,它允许多个线程并行持有锁,并发访问共享资源。
独占锁它所采用的是一种悲观的加锁策略, 对于写而言为了避免冲突独占是必须的,但是对于读就没有必要了,因为它不会影响数据的一致性。如果某个只读线程获取独占锁,则其他读线程都只能等待了,这种情况下就限制了不必要的并发性,降低了吞吐量。而共享锁则不同,它放宽了加锁的条件,采用了乐观锁机制,它是允许多个读线程同时访问同一个共享资源的。
举一个生活中的例子,有一条单行道路口有一红绿灯在正常的绿灯时间内如果骑车速度都很平均只能过去20辆车,这就意味着排在前面的20辆肯定能过去红绿灯,后面的就只能等下一个绿灯了。但是如果这个时候有车不想过去这个路口它驶向了边上别的路,那么后面的车就有机会。下面我们来看一个简单的例子:
public class TestSemaphore {
public static void main(String[] args) {
final Semaphore semaphore = new Semaphore(5);
ExecutorService executorService = Executors.newCachedThreadPool();
for(int i = 0;i<10;i++){
int j = 0;
executorService.submit(new A("car"+(j++),semaphore),"Thread"+(j++));
//new Thread(new A("car"+(j++),semaphore),"Thread"+(j++)).start();
if(i == 5){
try {
Thread.sleep(1000);
System.out.println("最后还有"+semaphore.availablePermits()+"个许可可用");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("最后还有"+semaphore.availablePermits()+"个许可可用");
}
}
class A implements Runnable{
String carName;
private Semaphore semaphore;
public A(String carName, Semaphore semaphore){
this.carName = carName;
this.semaphore = semaphore;
}
public void getWay(){
System.out.println("this car is get the way" + Thread.currentThread().getName());
}
public void run() {
try {
if(semaphore.availablePermits() > 0){
semaphore.acquire();
getWay();
semaphore.release();
}else{
System.out.println("请等待========");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
来源:https://www.cnblogs.com/rickiyang/p/11074264.html


猜你喜欢
- 说在前面:老项目、大项目适配Android X 注意了,一定要谨慎、谨慎、再谨慎。项目中用到的第三方库多的话会很麻烦,有些第三方库还没有适配
- Model与Session区别什么是Session:Session:在计算机中,尤其是在网络应用中,称为“会话”。它具体是指一个终端用户与交
- TaskAwaiter先说一下 TaskAwaiter,TaskAwaiter 表示等待异步任务完成的对象并为结果提供参
- windows下使用cmd命令提示符生成java webservice客户端代码,可以使用命令提示符直接生成客户端代码,直接导入到项目中,只
- 先随便搞个事件吧public class TestEventrgs : EventArgs {private st
- 1使用背景在实际项目中其中一部分逻辑可能会因为调用了外部服务或者等待锁等情况下出现不可预料的异常,在这个时候我们可能需要对调用这部分逻辑进行
- 创建一个列表消息卡片到目前为止,我们只有一个消息的卡片,看上去有点单调,所以让我们来改善它,让它拥有多条信息。我们需要创建一个能够显示多条消
- spring cloud常用依赖和配置整理常用依赖// pom.xml<?xml version="1.0" en
- 本文实例讲述了Android实现手机壁纸改变的方法。分享给大家供大家参考。具体如下:main.xml布局文件:<?xml versio
- 最近在看 C++ 的方法重载,我就在想 C# 中的重载底层是怎么玩的,很多朋友应该知道 C 是不支持重载的,比如下面的代码就会报错。#inc
- 有三种方法如下:三个方法都需要动态申请读写权限否则保存图片到相册也会失败方法一/** * 保存bitmap到本地
- 目前开发系统,附件文件一般都会使用第三方的存储空间来保存,一方面是为了开发者提供便利,另一方可以减轻系统的访问压力,下面介绍一下阿里云的OS
- 可能有些同学不明白,为啥要图片反转(不是旋转哦),我们在游戏开发中,为了节省图片资源(空间) 有可能会使用到图片反转,例如,一个人物图片,面
- 在项目中经常要用到将字符串解析成Locale,但是没有一个比较好用的类。java本身提供了3个构造函数,但是实际使用过程中,需要自己解析,比
- 自己的一个小项目使用redis在一个类里可以注入成功,而在另一个类以却不能注入成功不多bb直接上代码package com.common.u
- 异常是程序运行中发生的错误,异常处理是程序设计的一部分。错误的出现并不总是编写应用程序者的原因,有时候应用程序会因为终端用户的操作发生错误。
- 写在前面: 线程堆栈应该是多线程类应用程序非功能问题定位的最有效手段,可以说是杀手锏。线程堆栈最擅长与分析如下类型问题:系统无缘无故CPU过
- spring通过aop获取方法参数和参数值自定义注解package com.xiaolc.aspect; import java
- 本文实例讲述了Java Swing实现简单的体重指数(BMI)计算器功能。分享给大家供大家参考,具体如下:BMI,Body Mass Ind
- 前言最近使用QT中的QTextEdit控件,作为实时数据显示的UI,在一次写入超过多少k的时候循环写入则会卡顿,网上也没有什么好的解决方案,