Semaphore 的理解
来源:互联网 发布:qq群发软件下载 编辑:程序博客网 时间:2024/05/23 16:23
转载博客:http://blog.csdn.net/lmj623565791/article/details/26810813
今天介绍Semaphore,同样在Java.util.concurrent包下。本来准备通过例子,从自己实现到最后使用并发工具实现,但是貌似效果并不是很好,有点太啰嗦的感觉,所有准备直入主题。
介绍:Semaphore中管理着一组虚拟的许可,许可的初始数量可通过构造函数来指定【new Semaphore(1);】,执行操作时可以首先获得许可【semaphore.acquire();】,并在使用后释放许可【semaphore.release();】。如果没有许可,那么acquire方法将会一直阻塞直到有许可(或者直到被终端或者操作超时)。
作用:可以用来控制同时访问某个特定资源的操作数量,或者某个操作的数量。下面使用Semaphore实现两个例子:
1、互斥
大家都学过操作系统,都知道互斥的概念,比较简单的互斥实现,比如PV操作,判断资源,然后忙等实现互斥;上一篇博客也说过,忙等对CPU的消耗巨大,下面我们通过Semaphore来实现一个比较好的互斥操作:
假设我们公司只有一台打印机,我们需要对这台打印机的打印操作进行互斥控制:
package com.zhy.concurrency.semaphore; import java.util.concurrent.Semaphore; /** * 使用信号量机制,实现互斥访问打印机 * * @author zhy * */ public class MutexPrint { /** * 定义初始值为1的信号量 */ private final Semaphore semaphore = new Semaphore(1); /** * 模拟打印操作 * @param str * @throws InterruptedException */ public void print(String str) throws InterruptedException { //请求许可 semaphore.acquire(); System.out.println(Thread.currentThread().getName()+" enter ..."); Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "正在打印 ..." + str); System.out.println(Thread.currentThread().getName()+" out ..."); //释放许可 semaphore.release(); } public static void main(String[] args) { final MutexPrint print = new MutexPrint(); /** * 开启10个线程,抢占打印机 */ for (int i = 0; i < 10; i++) { new Thread() { public void run() { try { print.print("helloworld"); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); } } }
输出结果:
Thread-1 enter ... Thread-1正在打印 ...helloworld Thread-1 out ... Thread-2 enter ... Thread-2正在打印 ...helloworld Thread-2 out ... Thread-0 enter ... Thread-0正在打印 ...helloworld Thread-0 out ... Thread-3 enter ... Thread-3正在打印 ...helloworld Thread-3 out ...
通过初始值为1的Semaphore,很好的实现了资源的互斥访问。
2、连接池的模拟实现
在项目中处理高并发时,一般数据库都会使用数据库连接池,假设现在数据库连接池最大连接数为10,当10个连接都分配出去以后,现在有用户继续请求连接,可能的处理:
a、手动抛出异常,用户界面显示,服务器忙,稍后再试
b、阻塞,等待其他连接的释放
从用户体验上来说,更好的选择当然是阻塞,等待其他连接的释放,用户只会觉得稍微慢了一点,并不影响他的操作。下面使用Semaphore模拟实现一个数据库连接池:
package com.zhy.concurrency.semaphore; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Semaphore; /** * 使用Semaphore模拟数据库链接池的使用 * @author zhy * */ public class ConnectPool { private final List<Conn> pool = new ArrayList<Conn>(3); private final Semaphore semaphore = new Semaphore(3); /** * 初始化分配3个连接 */ public ConnectPool() { pool.add(new Conn()); pool.add(new Conn()); pool.add(new Conn()); } /** * 请求分配连接 * @return * @throws InterruptedException */ public Conn getConn() throws InterruptedException { semaphore.acquire(); Conn c = null ; synchronized (pool) { c = pool.remove(0); } System.out.println(Thread.currentThread().getName()+" get a conn " + c); return c ; } /** * 释放连接 * @param c */ public void release(Conn c) { pool.add(c); System.out.println(Thread.currentThread().getName()+" release a conn " + c); semaphore.release(); } public static void main(String[] args) { final ConnectPool pool = new ConnectPool(); /** * 第一个线程占用1个连接3秒 */ new Thread() { public void run() { try { Conn c = pool.getConn(); Thread.sleep(3000); pool.release(c); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); /** * 开启3个线程请求分配连接 */ for (int i = 0; i < 3; i++) { new Thread() { public void run() { try { Conn c = pool.getConn(); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); } } private class Conn { } }
输出结果
Thread-0 get a conn com.zhy.concurrency.semaphore.ConnectPool$Conn@12b6651 Thread-2 get a conn com.zhy.concurrency.semaphore.ConnectPool$Conn@e53108 Thread-1 get a conn com.zhy.concurrency.semaphore.ConnectPool$Conn@1888759 Thread-0 release a conn com.zhy.concurrency.semaphore.ConnectPool$Conn@12b6651 Thread-3 get a conn com.zhy.concurrency.semaphore.ConnectPool$Conn@12b6651
我们测试时,让Thread-0持有一个连接3秒,然后瞬间让3个线程再去请求分配连接,造成Thread-3一直等到Thread-0对连接的释放,然后获得连接。
通过两个例子,基本已经了解了Semaphore的用法,这里的线程池例子只是为了说明Semaphore的用法,真实的实现代码比这复杂的多,而且可能也不会直接用Semaphore。
- Semaphore 的理解
- Semaphore的简单理解
- 理解JAVA的Semaphore信号量
- 对信号量Semaphore的理解与运用
- 理解Semaphore和Mutex
- 理解Semaphore和Mutex
- 线程中的Semaphore理解
- 理解Semaphore和Mutex
- Semaphore(信号量)理解
- 深入理解Semaphore
- java并发工具Semaphore的理解和使用
- 理解Semaphore及其用法详解
- Semaphore, CountDownLatch,CyclicBarrier 简单理解
- 理解Semaphore及其用法详解
- 理解Semaphore及其用法详解
- 深入学习理解java:高效的解决死锁问题的线程通讯方式:Semaphore 和 BlockingQueue
- Semaphore 的小探索
- semaphore的笔记
- 模板学习笔记1
- 线性规划、梯度下降、正规方程组——斯坦福ML公开课笔记1-2
- jqgrid使用
- IOS 空值 nil Nil NULL NSNull kCFNull
- docker详细的基础用法
- Semaphore 的理解
- 滑动界面
- C# .Net操作XML文件
- 将多个凸包连接起来形成一个大凸包找到最接近的轮廓
- [从头学数学] 第287节 [计算几何] 多边形的布尔运算(中)
- CentOS6x上安装Postgresql 9.x
- 微信授权接口封装
- jwplayer +ffmpeg+red5 实现摄像头的直播
- hbuilder安装高版本SVN