-
疯狂创客圈 经典图书 : 《Netty Zookeeper Redis 高并发实战》 面试必备 + 面试必备 + 面试必备 【博客园总入口 】
-
疯狂创客圈 经典图书 : 《SpringCloud、Nginx高并发核心编程》 大厂必备 + 大厂必备 + 大厂必备 【博客园总入口 】
-
入大厂+涨工资必备: 高并发【 亿级流量IM实战】 实战系列 【 SpringCloud Nginx秒杀】 实战系列 【博客园总入口 】
JUC 高并发工具类 3文章:
1 Semaphore是什么?
Semaphore是计数信号量。Semaphore管理一系列许可。每个acquire方法阻塞,直到有一个许可证可以获得然后拿走一个许可证;每个release方法增加一个许可,这可能会释放一个阻塞的acquire方法。然而,其实并没有实际的许可这个对象,Semaphore只是维持了一个可获得许可证的数量。
比如:停车场入口立着的那个显示屏,每有一辆车进入停车场显示屏就会显示剩余车位减1,每有一辆车从停车场出去,显示屏上显示的剩余车辆就会加1,当显示屏上的剩余车位为0时,停车场入口的栏杆就不会再打开,车辆就无法进入停车场了,直到有一辆车从停车场出去为止。
比如:在学生时代都去餐厅打过饭,假如有3个窗口可以打饭,同一时刻也只能有3名同学打饭。第四个人来了之后就必须在外面等着,只要有打饭的同学好了,就可以去相应的窗口了 。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fhj3NWT2-1604139314540)(https://pics5.baidu.com/feed/e1fe9925bc315c6004ec19b8f2c86e16485477ee.jpeg?token=4e4314eeaf79a48cc2cc9003bdf22d27&s=8D26F4170993F3E902C5DD4C03007073)]
2 怎么使用 Semaphore
2.1 构造方法
//创建具有给定的许可数和非公平的公平设置的 Semaphore。
Semaphore(int permits)
//创建具有给定的许可数和给定的公平设置的 Semaphore。
Semaphore(int permits, boolean fair)
2.2 重要方法
在上面我们使用最基本的acquire方法和release方法就可以实现Semaphore最常见的功能,不过其他方法还是需要我们去了解一下的。
1、acquire(int permits)
从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。就好比是一个学生占两个窗口。这同时也对应了相应的release方法。
2、release(int permits)
释放给定数目的许可,将其返回到信号量。这个是对应于上面的方法,一个学生占几个窗口完事之后还要释放多少
3、availablePermits()
返回此信号量中当前可用的许可数。也就是返回当前还有多少个窗口可用。
4、reducePermits(int reduction)
根据指定的缩减量减小可用许可的数目。
5、hasQueuedThreads()
查询是否有线程正在等待获取资源。
6、getQueueLength()
返回正在等待获取的线程的估计数目。该值仅是估计的数字。
7、tryAcquire(int permits, long timeout, TimeUnit unit)
如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。
8、acquireUninterruptibly(int permits)
从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
3 使用案例
这个案例使用的就是我们之前的小例子,也就是去餐厅打饭的案例。
我们先看Test类:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FS6locSZ-1604139314543)(https://pics3.baidu.com/feed/472309f790529822787d1d77a9b3dece0b46d4b2.jpeg?token=4e2d7f2dfdf9be3f1a3f16fda56b967b&s=BA81A14C47F09868165999130000E081)]
在这个代码中我们看到,主要是new了一个Semaphore,然后赋给每一位同学Student,接下来我们就来好好看看Student线程是如何实现的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZiBxQx9P-1604139314544)(https://pics4.baidu.com/feed/2f738bd4b31c870154037c6659063b2a0608ff7d.jpeg?token=a01971796d2bdc9e96b2e1d0563fb96a&s=3281B14CD2B4966F56D9B50F000070C1)]
在这个Student类中我们最主要看run方法的实现,首先我们通过acquire获取了当前窗口的许可,然后休眠3秒代表打饭,最后在finally使用release方法释放这个窗口许可证。代码很简单,原理很清楚,我们测试一波:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5jnNutK9-1604139314547)(https://pics0.baidu.com/feed/58ee3d6d55fbb2fbfe163bf6313385a14723dc90.jpeg?token=4dc06098df214c105b05dfe933528c9e&s=479C2D2A114F554F1C613CDA000050B4)]
这个结果你也看到了,基本上同一时刻只能有三个学生在窗口旁边。
在这里你可能有一个疑问了,Semaphore好像和synchronized关键字没什么区别,都可以实现同步,如果是这样那说明我们还没有真正理解jdk的注释,他只是限制了访问某些资源的线程数,其实并没有实现同步,我们可以看一下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O2oWAgxb-1604139314549)(https://pics7.baidu.com/feed/c995d143ad4bd113e91ab29724d6010a4afb053a.jpeg?token=195052e5fe3b9252fcc25d2ac11fe879&s=3A81A14C52F4AC69045D180B0000F0C0)]
现在我们在获取许可前增加了一条输

本文详细介绍了Java并发工具类Semaphore的原理、使用方法和常见应用场景,包括其在并发控制中的作用,如限制并发线程数量、模拟资源池等。通过实例展示了Semaphore如何实现线程同步与互斥,并解析了其内部的获取和释放许可的源码流程。
最低0.47元/天 解锁文章
1007

被折叠的 条评论
为什么被折叠?



