Java并发编程系列之Semaphore详解
简单介绍
我们以饭店为例,假设饭店只有三个座位,一开始三个座位都是空的。这时如果同时来了三个客人,服务员人允许他们进去用餐,然后对外说暂无座位。后来的客人必须在门口等待,直到有客人离开。这时,如果有一个客人离开,服务员告诉客人,可以进来用餐,如果又有客人离开,则又可以进来客人用餐,如此往复。
在这个饭店中,座位是公共资源,每个人好比一个线程,服务员起的就是信号量的作用。信号量是一个非负整数,表示了当前公共资源的可用数目(在上面的例子中可以用空闲的座位类比信号量),当一个线程要使用公共资源时(在上面的例子中可以用客人比线程),首先要查看信号量,如果信号量的值大于1,则将其减1,然后去占有公共资源。如果信号量的值为0,则线程会将自己阻塞,直到有其它线程释放公共资源。
1、简单介绍Semaphore
a、可用来控制同时访问特定资源的线程数量,以此来达到协调线程工作。
b、维护了一个虚拟的资源池,如果许可为0则线程阻塞等待,直到许可大于0时又可以有机会获取许可了。
c、 内部也有公平锁、非公平锁来访问资源的静态内部类。
2、Semaphore方法
a、public Semaphore(int permits);// 创建一个给定许可数量的信号量对象,且默认以非公平锁方式获取资源
b、public Semaphore(int permits, boolean fair);//创建一个给定许可数量的信号量对象,且是否公平方式由传入的fair布尔参数值决定
c、public void acquire() ;//从此信号量获取一个许可,当许可数量小于零时,则阻塞等待
d、public void acquire(int permits) ;//从此信号量获取permits个许可,当许可数量小于零时,则阻塞等待,但是当阻塞等待的线程被唤醒后发现被中断过的话则会抛InterruptedException异常
e、public void acquireUninterruptibly(int permits) ;从此信号量获取permits个许可,当许可数量小于零时,则阻塞等待,但是当阻塞等待的线程被唤醒后发现被中断过的话则不会抛InterruptedException异常
f、public void release();//释放一个许可
g、public void release(int permits);释放permits个许可
以上只是列出主要方法名,方法详细解释,Semaphore类上面都有注释。就不一一累出来了。
举一个简单例子,帮助我们加深印象
/** * @author shuliangzhao * @Title: SemaPhoreTest * @ProjectName design-parent * @Description: TODO * @date 2019/6/5 22:50 */ public class SemaPhoreTest { private Semaphore semaphore = new Semaphore(3); class TaskThread implements Runnable{ private int id; public TaskThread(int id) { this.id = id; } @Override public void run() { try { semaphore.acquire(); System.out.println("Thread " + id + " is working"); Thread.sleep(2000); semaphore.release(); System.out.println("Thread " + id + " is over"); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { SemaPhoreTest semaPhoreTest = new SemaPhoreTest(); /*for (int i = 0;i<6;i++) { Thread thread = new Thread(semaPhoreTest.new TaskThread(i)); thread.start(); }*/ ExecutorService executorService = Executors.newCachedThreadPool();//同步队列线程 executorService.submit(semaPhoreTest.new TaskThread(1)); executorService.submit(semaPhoreTest.new TaskThread(2)); executorService.submit(semaPhoreTest.new TaskThread(3)); executorService.submit(semaPhoreTest.new TaskThread(4)); executorService.submit(semaPhoreTest.new TaskThread(5)); executorService.submit(semaPhoreTest.new TaskThread(6)); executorService.submit(semaPhoreTest.new TaskThread(7)); executorService.shutdown(); } }
运行结果
- 完整详解GCD系列(四)dispatch_semaphore(信号量)
- Java并发编程系列之CyclicBarrier详解
- 完整详解GCD系列(四)dispatch_semaphore(信号量)
- Java并发编程最佳实例详解系列
- iOS学习笔记74-完整详解GCD系列(四)dispatch_semaphore(信号量)
- Java并发编程系列之二十三:Semaphore
- Java并发编程系列(二)----synchronized锁详解
- java并发编程系列之Semaphore信号量的使用
- 完整详解swift GCD系列(四)dispatch_semaphore(信号量)
- git详解系列
- Spring系列【05】@Autowired详解(补充)
- 深入理解JavaScript系列(43):设计模式之状态模式详解
- Android Studio系列教程五--Gradle命令详解与导入第三方包
- WIN2012案例系列3:域还原后验证失败故障详解
- 自动化测试 - RFT系列教程11: RFT中的描述性编程 - 详解find方法
- Android Studio系列教程五--Gradle命令详解与导入第三方包
- Java常见笔试面试题目深度剖析系列之:Java方法参数传递详解
- J2EE系列之Spring4学习笔记(三)--IOC详解(依赖注入)
- 《视频直播技术详解》系列之一:开篇