Java 信号量Semaphore的实现
作者:全王工二一 发布时间:2023-06-19 11:00:34
标签:Java,信号量,Semaphore
近日于LeetCode看题遇1114 按序打印,获悉一解法使用了Semaphore,顺势研究,记心得于此。
此解视Semaphore为锁,以保证同一时刻单线程的顺序执行。在此原题上,我作出如下更改。
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
static Semaphore A;
static Semaphore B;
static Semaphore C;
public static void main(String[] args) throws InterruptedException {
A = new Semaphore(1);
B = new Semaphore(0);
C = new Semaphore(0);
ExecutorService ex=Executors.newFixedThreadPool(10);
for (int i = 0; i <7; i++) {
ex.execute(new R1());
ex.execute(new R2());
ex.execute(new R3());
}
ex.shutdown();
}
public static class R1 implements Runnable{
@Override
public void run() {
try {
// A.acquire();
System.out.println("1"+Thread.currentThread().getName());
// B.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static class R2 implements Runnable{
@Override
public void run() {
try {
// B.acquire();
System.out.println("2"+Thread.currentThread().getName());
// C.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static class R3 implements Runnable{
@Override
public void run() {
try {
// C.acquire();
System.out.println("3"+Thread.currentThread().getName());
// A.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
10个线程的常量池中,分别调用R1,R2,R3的方法多次,控制台输出对应各方法名拼接执行该方法的线程名。多次执行结果各不相同:
1pool-1-thread-1
2pool-1-thread-2
1pool-1-thread-4
3pool-1-thread-6
2pool-1-thread-5
3pool-1-thread-3
1pool-1-thread-7
2pool-1-thread-8
3pool-1-thread-9
3pool-1-thread-1
2pool-1-thread-8
1pool-1-thread-4
3pool-1-thread-1
1pool-1-thread-2
2pool-1-thread-9
1pool-1-thread-10
3pool-1-thread-1
2pool-1-thread-5
1pool-1-thread-6
3pool-1-thread-4
2pool-1-thread-8
1pool-1-thread-1
2pool-1-thread-2
3pool-1-thread-3
1pool-1-thread-4
2pool-1-thread-5
3pool-1-thread-6
1pool-1-thread-7
2pool-1-thread-8
3pool-1-thread-9
1pool-1-thread-10
3pool-1-thread-1
1pool-1-thread-4
2pool-1-thread-8
3pool-1-thread-3
2pool-1-thread-10
1pool-1-thread-2
2pool-1-thread-9
3pool-1-thread-4
1pool-1-thread-7
3pool-1-thread-6
2pool-1-thread-5
方法能调用,多线程下却无法保证方法的顺序执行。使用Semaphore后,代码为:
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
static Semaphore A;
static Semaphore B;
static Semaphore C;
public static void main(String[] args) throws InterruptedException {
A = new Semaphore(1);
B = new Semaphore(0);
C = new Semaphore(0);
ExecutorService ex=Executors.newFixedThreadPool(10);
for (int i = 0; i <7; i++) {
ex.execute(new R1());
ex.execute(new R2());
ex.execute(new R3());
}
ex.shutdown();
}
public static class R1 implements Runnable{
@Override
public void run() {
try {
A.acquire();
System.out.println("1"+Thread.currentThread().getName());
B.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static class R2 implements Runnable{
@Override
public void run() {
try {
B.acquire();
System.out.println("2"+Thread.currentThread().getName());
C.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static class R3 implements Runnable{
@Override
public void run() {
try {
C.acquire();
System.out.println("3"+Thread.currentThread().getName());
A.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
多次运行结果皆能保证1、2、3的顺序:
1pool-1-thread-1
2pool-1-thread-2
3pool-1-thread-3
1pool-1-thread-4
2pool-1-thread-5
3pool-1-thread-6
1pool-1-thread-7
2pool-1-thread-8
3pool-1-thread-9
1pool-1-thread-10
2pool-1-thread-1
3pool-1-thread-2
1pool-1-thread-3
2pool-1-thread-4
3pool-1-thread-5
1pool-1-thread-6
2pool-1-thread-9
3pool-1-thread-7
1pool-1-thread-10
2pool-1-thread-8
3pool-1-thread-1
附上api文档链接 Semaphore
A = new Semaphore(1);
B = new Semaphore(0);
C = new Semaphore(0);
进入R2、R3方法的线程会执行acquire()方法,而B、C中的计数器为0获取不到许可,阻塞直到一个可用,或者线程被中断,不能继续执行。R1方法中A尚有1个许可可拿到,方法执行,并给B发布一个许可,若B先于A执行acquire(),此时B为阻塞状态,则获取到刚刚发布的许可,该线程被重新启用。
来源:https://blog.csdn.net/laybarbarian/article/details/98586742


猜你喜欢
- state:比较常用,各种状态都可以用它,但是它更着重于一种心理状态或者物理状态。Status:用在人的身上一般是其身份和地位,作“状态,情
- Google 发布的Material Design支持库,对我们的APP设计有很大的影响,如果重新设计APP,支持库应该直接用V4提升到V7
- 当我们在windows系统下安装完jdk时,测试案例HelloWorld;运行java命令时报错:找不到或无法加载主类解决方法:1.首先检查
- 服务提供者@GetMapping("/{id}") public void queryJobInfoLogD
- 当采用HttpClient httpClient = HttpClients.createDefault() 实例化的时候。会导致Addre
- 前几天刚好有需求要把emoji对应的Unicode编码转换成文字,比如1f601对应的这个笑脸😁,但没有找到C#的把1f601转换成文字的方
- 一、电子邮件详解假设自己的电子邮件是me@163.com,对方的邮件是you@163.com我们编写好文件填写好对方文件,点击发送,这些电子
- 本文为大家分享了Android中Drawable方法的详细使用方法,供大家参考,具体内容如下1. BitmapDrawable相关方法:新建
- .NET 4.0中新增了一个System.Runtime.Caching的名字空间,它提供了一系列可扩展的Cache框架,本文就简单的介绍一
- C#中,Image为源自 Bitmap 和 Metafile 的类提供功能的抽象基类,也就是说更通用,当我们用Image.FromFile(
- 模式介绍桥接模式(Bridge模式)是指:将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。是一种结构型设计模式。Bridge模式
- 项目结构这个是在网上找的资源,出处记不得了,记录一下。程序的总体结构,很简单的:核心代码代码如下:ArrComparator.java类im
- java线程同步原理java会为每个object对象分配一个monitor,当某个对象的同步方法(synchronizedmethods)被
- 记录下一个很实用的小控件EditTextWithDel,就是在Android系统的输入框右边加入一个小图标,点击小图标可以清除输入框里面的内
- 对于某些程序,我们只允许它使用某些特定端口、网络类型或者特定IP类型等信息。这时候,需要使用到防火墙里面的“高级设置”,创建某些特定的入站或
- 在进行C#程序设计时,用的最多的莫过于string了,但有些时候由于不仔细或者基础的不牢固等因素容易出错,今天本文就来较为详细的总结一下C#
- SmartArt其实就是一个文字的可视化工具,用户可在PowerPoint,Word,Excel中使用该特性创建各种图形图表。SmartAr
- 目录首先必须要有一个个人微信公众号效果图后台路由代码完整代码首先必须要有一个个人微信公众号个人微信公众号相关的接口权限有限,不过用于个人学习
- 本文实例讲述了Java实现二叉树的深度优先遍历和广度优先遍历算法。分享给大家供大家参考,具体如下:1. 分析二叉树的深度优先遍历的非递归的通
- 上一节我们了解了Lock接口的一些简单的说明,知道Lock锁的常用形式,那么这节我们正式开始进入JUC锁(java.util.concurr