[TOC]
一、什么是信号量
“信号量”在编程术语中应用单词semaphore,那什么是“信号量”?信号量就好比你家厨房入口架子上摆了三把锅。
- 如果你的孩子热奶拿走一把,你的老婆热汤拿走一把,你的妈妈做菜拿走一把,你想煮面条就没有锅了。当你看到这种状况,你就不会进入厨房了,你处于期待状态。也就说厨房依照“锅的数量”作为信号量,只能包容三个人(线程)。
- 当你的老婆热完汤之后,把锅从新放回架子上,你就能够去取得一个锅,你就能够进入厨房了。
二、信号量类Semaphore
通过上文的介绍,咱们能够总结出信号量的重要组成部分
- 计数器:计算信号量的应用状况,锅(信号)被应用一次减1,锅(信号)被还回一次加1
- 期待队列:当工作数量大于信号量数量下限的时候,工作进入期待队列
信号量在JDK中是由 java.util.concurrent.Semaphore 实现的,Semaphore提供了两个构造函数。permits参数代表信号量的数量(锅的数量),fair代表信号量的获取是否遵循偏心准则。所谓的偏心准则就是:先启动的线程先调用semaphore.acquire();
办法,就先失去一个信号“锅”(permit),遵循先来后到的准则。
public Semaphore(int permits)public Semaphore(int permits, boolean fair)
罕用办法列表
办法名 | 作用 |
---|---|
acquire() | 获取一个permit,在获取到permit之前,线程处于阻塞状态 |
tryAcquire() | 尝试获取一个permit,获取胜利返回true,否则返回false,不阻塞线程 |
tryAcquire(long timeout, TimeUnit unit) | 和tryAcquire()大部分实现一样,区别是提供超时设置,在超时工夫范畴内屡次尝试,不阻塞线程。 |
availablePermits() | 获取目前残余的信号permit的数量 |
release() | 开释一个permit,并唤醒一个期待信号permit的线程 |
hasQueuedThreads() | 返回值boolean类型,判断期待队列中是否存在期待线程 |
getQueueLength() | 获取期待队列中期待线程的数量 |
三、实现限流器
通过下面的介绍,我置信大家必定能够想到Semaphore的利用场景。比方:
- 医院门诊排号器,三个在岗医生就是3个信号permit,当超出信号量数量的时候,想就诊就只能期待
- 停车场停车性能,n个车位就是n个信号permit,当超出信号量数量的时候,想停车也只能期待
利用场景还有很多很多,大家本人去发会创造力吧。其实无论多少种利用场景说白了:Semaphore实现的就是一个限流器。咱们还是以咱们家的厨房kitchen外面的三把锅wok为例,实现基于信号量的限流。
public class TestKitchenSemaphore { //信号量-3把锅 private static Semaphore threeWoks = new Semaphore(3); public static void main(String[] args) throws InterruptedException { //模仿5集体抢占3把锅的场景 for(int i=0;i < 5;i++){ Thread.sleep(1000); //模仿进入厨房的先后顺序,存在工夫距离 new Thread(() -> { try { threeWoks.acquire(); //获取一个permit,信号量计数器减1 System.out.println(Thread.currentThread().getName() + "拿走了一把锅,还剩" + threeWoks.availablePermits() + "把锅"); Thread.sleep(new Random().nextInt(5000)); //模仿应用锅的时长 threeWoks.release();//开释permit,信号量计数器加1 System.out.println(Thread.currentThread().getName() + "还回一把锅,还剩" + threeWoks.availablePermits() + "把锅"); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } }}
上文代码的输入如下,咱们能够看到每acquire一次信号量减1,每release一次信号量加1。信号量的下限是3,上限是0。当达到下限的时候,只有等先占据锅permit的线程开释,其余线程能力获取到锅permit。
Thread-0拿走了一把锅,还剩2把锅 Thread-1拿走了一把锅,还剩1把锅Thread-2拿走了一把锅,还剩0把锅 => 备注:5个线程只能获取3个锅(下限)Thread-1还回一把锅,还剩1把锅Thread-3拿走了一把锅,还剩0把锅 => 备注:被还回能力被再次占用,不超过3Thread-0还回一把锅,还剩1把锅Thread-4拿走了一把锅,还剩0把锅 => 备注:被还回能力被再次占用,不超过3Thread-2还回一把锅,还剩1把锅 Thread-3还回一把锅,还剩2把锅Thread-4还回一把锅,还剩3把锅 => 备注:用完顺次开释
欢送关注我的博客,更多精品常识合集
本文转载注明出处(必须带连贯,不能只转文字):字母哥博客 - zimug.com
感觉对您有帮忙的话,帮我点赞、分享!您的反对是我不竭的创作能源!。另外,笔者最近一段时间输入了如下的精品内容,期待您的关注。
- 《kafka修炼之道》
- 《手摸手教你学Spring Boot2.0》
- 《Spring Security-JWT-OAuth2一本通》
- 《实战前后端拆散RBAC权限管理系统》
- 《实战SpringCloud微服务从青铜到王者》