java concurrent信号量_【Java并发编程五】信号量

一、概述

技术信号量用来控制能够同时访问某特定资源的活动的数量,或者同时执行某一给定操作的数据。计数信号量可以用来实现资源池或者给一个容器限定边界。

信号量维护了一个许可集,许可的初始量通过构造函数传递给Semaphore。活动能够获取许可,并在使用之后释放许可,如果没有可用的许可,acquire方法会被阻塞,直到有可用的为止。每个release方法添加一个许可,从而可能释放一个正在阻塞的获取者。

计算信号量的一种退化形式是二元信号量:一个计数初始值为1的Semaphore,二元信号量可用作互斥锁。

二、应用场景

信号量可用来实现资源池,比如数据库连接池。示例代码如下:

classPool

{private static final int MAX_AVAILABLE = 100;private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);public Object getItem() throwsInterruptedException

{

available.acquire();returngetNextAvailableItem();

}public voidputItem(Object x)

{if(markAsUnused(x))

available.release();

}

MyResource resource1=new MyResource("资源1");

MyResource resource2=new MyResource("资源2");

MyResource resource3=new MyResource("资源3");protected MyResource[] items = newMyResource[]{resource1,resource2,resource3};protected boolean[] used = new boolean[MAX_AVAILABLE];protected synchronizedObject getNextAvailableItem()

{for (int i = 0; i < MAX_AVAILABLE; ++i)

{if (!used[i])

{

used[i]= true;returnitems[i];

}

}return null; //not reached

}protected synchronized booleanmarkAsUnused(Object item)

{for (int i = 0; i < MAX_AVAILABLE; ++i)

{if (item ==items[i])

{if(used[i])

{

used[i]= false;return true;

}else

return false;

}

}return false;

}

}classMyResource

{

String resourceName;publicMyResource(String resourceName)

{this.resourceName=resourceName;

}

}

三、使用方法

构造函数:

Semaphore(int permits):创建具有给定许可数和非公平设置的Semaphore

Semaphore(int permits,boolean fair):此类的构造方法可选地接受一个公平 参数。当设置为 false 时,此类不对线程获取许可的顺序做任何保证。特别地,闯入是允许的,也就是说可以在已经等待的线程前为调用 acquire() 的线程分配一个许可,从逻辑上说,就是新线程将自己置于等待线程队列的头部。当公平设置为 true 时,信号量保证对于任何调用获取方法的线程而言,都按照处理它们调用这些方法的顺序(即先进先出;FIFO)来选择线程、获得许可。注意,FIFO 排序必然应用到这些方法内的指定内部执行点。所以,可能某个线程先于另一个线程调用了 acquire,但是却在该线程之后到达排序点,并且从方法返回时也类似。

Semaphore还提供一些其他方法:

int availablePermits() :返回此信号量中当前可用的许可证数。

int getQueueLength():返回正在等待获取许可证的线程数。

boolean hasQueuedThreads() :是否有线程正在等待获取许可证。

void reducePermits(int reduction) :减少reduction个许可证。是个protected方法。

Collection getQueuedThreads() :返回所有等待获取许可证的线程集合。是个protected方法。

示例代码如下:

public classSemaphoreTest

{public static voidmain(String[] args)

{

Semaphore semaphore=new Semaphore(3);for(int i=0;i<5;i++)

{

MyThread myThread=new MyThread("线程"+i, semaphore);

myThread.start();

}

}static class MyThread extendsThread

{

String name;

Semaphore semaphore;publicMyThread(String name,Semaphore semaphore)

{this.name=name;this.semaphore=semaphore;

}

@Overridepublic voidrun()

{try{

semaphore.acquire();

System.out.println(name+"获取信号量,开始工作...");

Thread.sleep(3000);

System.out.println(name+"工作结束"+",正在等待获取许可证的线程数:"+semaphore.getQueueLength());

}catch(InterruptedException e)

{//TODO 自动生成的 catch 块

e.printStackTrace();

}finally{

semaphore.release();

}

}

}

}

执行结果如下:

0fe22a0f5a9885508529f3f014a31e2c.png

四、参考资料

1、Java并发编程实践

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值