Java 7之多线程- Semaphore--转载
Semaphore用于保存当前可用许可的数量。是通过共享锁实现的。根据共享锁的获取原则,Semaphore分为"公平信号量"和"非公平信号量"。 "公平信号量"和"非公平信号量"的释放信号量的机制是一样的!不同的是它们获取信号量的机制:线程在尝试获取信号量许可时,对于公平信号量而言,如果当前线程不在队列的头部,则排队等候;而对于非公平信号量而言,无论当前线程是不是在队列的头部,它都会直接获取信号量。该差异具体的体现在,它们的tryAcquireShared()函数的实现不同。 如果要使用Semaphore对象时,首先通过构造函数取得对象,如下: Semaphore( permits) {
sync = Semaphore( permits, fair) {
sync = fair ? FairSync(permits) :
然后就可以调用Semaphore对象进行信号量的获取了,如下: acquire() 1<span style="color: #0000ff;">public <span style="color: #0000ff;">void acquire(<span style="color: #0000ff;">int permits) <span style="color: #0000ff;">throws<span style="color: #000000;"> InterruptedException {
<span style="color: #0000ff;">if (permits < 0) <span style="color: #0000ff;">throw <span style="color: #0000ff;">new<span style="color: #000000;"> IllegalArgumentException(); sync.acquireSharedInterruptibly(permits); } 1、公平信号量的获取 首先来看公平信号量的获取,方法如下: acquireSharedInterruptibly( arg)
(tryAcquireShared(arg) < 0
如果tryAcquireShared()方法获取失败,通常会返回一个小于0的数量。Semaphore中公平锁对应的tryAcquireShared()实现如下: tryAcquireShared(
-1 available = getState();
remaining = available -=0”,则设置可以获得的信号量许可数为remaining。
(remaining < 0 ||
返回的是remaining,如果为-1,表示获取失败。如果为>=0,则预示了其他共享获取操作能否成功。 如上方法获取失败后,调用doAcquireSharedInterruptibly()方法,如下: doAcquireSharedInterruptibly( arg)
Node node = failed =
Node p = (p == r = (r >= 0= ;
failed =
(shouldParkAfterFailedAcquire(p,node) &&
2、非公平信号量的获取 tryAcquireShared(
在这个方法里调用了如下方法: nonfairTryAcquireShared( acquires) {
available = remaining = available - (remaining < 0 || compareAndSetState(available,remaining))=0,则通过CAS方式更新当前许可的数量
判断当前剩余的信号量许可数,返回小于0的数表示获取失败,大于等于0表示成功。 非公平和公平主要体现在tryAcquireShared()方法的实现上。 (1)非公平获取 如果当前可用的信号量许可大于等于请求数,则通过CAS修改剩余许可量并返回,如果小于的话,返回小于0的数,表示获取失败。 (2)公平获取 在获取时还会判断。如果当前线程不在队列的头部,则返回-1,排队等候;然后再去判断信号量许可。 3、公平信号量的释放 调用如下方法来释放信号量许可,如下: 1<span style="color: #0000ff;">public <span style="color: #0000ff;">void release(<span style="color: #0000ff;">int<span style="color: #000000;"> permits) {
<span style="color: #0000ff;">if (permits < 0) <span style="color: #0000ff;">throw <span style="color: #0000ff;">new<span style="color: #000000;"> IllegalArgumentException(); sync.releaseShared(permits); } 调用无参数的release()方法默认只释放一个信号量许可,而下面的可以指定: releaseShared(
首先调用tryReleaseShared()方法去释放,源代码如下: tryReleaseShared(
current =
next = current + (next < current)
Error("Maximum permit count exceeded"
如果tryReleaseShared()尝试释放共享锁失败,则会调用doReleaseShared()去释放共享锁。doReleaseShared()的源码如下
Node h =
(h != && h !=
ws =
(ws ==
(!compareAndSetWaitStatus(h,Node.SIGNAL,0
(ws == 0 &&
!compareAndSetWaitStatus(h,0;
(h == head)
4、非公平信号量的释放 tryAcquireShared( nonfairTryAcquireShared(
available =
remaining = available -=0,则设置可以获得的信号量许可数为remaining
(remaining < 0 ||
举个例子,如下: <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> SemaphoreTest1 {
<span style="color: #0000ff;">private <span style="color: #0000ff;">static <span style="color: #0000ff;">final <span style="color: #0000ff;">int SEM_MAX = 10<span style="color: #000000;">; <span style="color: #0000ff;">public <span style="color: #0000ff;">static <span style="color: #0000ff;">void<span style="color: #000000;"> main(String[] args) { Semaphore sem = <span style="color: #0000ff;">new<span style="color: #000000;"> Semaphore(SEM_MAX); <span style="color: #008000;">//<span style="color: #008000;">创建线程池 ExecutorService threadPool = Executors.newFixedThreadPool(3<span style="color: #000000;">); <span style="color: #008000;">//<span style="color: #008000;">在线程池中执行任务 threadPool.execute(<span style="color: #0000ff;">new MyThread(sem,5<span style="color: #000000;">)); threadPool.execute(<span style="color: #0000ff;">new MyThread(sem,4<span style="color: #000000;">)); threadPool.execute(<span style="color: #0000ff;">new MyThread(sem,7<span style="color: #000000;">)); <span style="color: #008000;">//<span style="color: #008000;">关闭池 <span style="color: #000000;"> threadPool.shutdown(); } } <span style="color: #0000ff;">class MyThread <span style="color: #0000ff;">extends<span style="color: #000000;"> Thread {
<span style="color: #000000;"> sem.acquire(count);
<span style="color: #000000;"> sem.release(count); 某一次运行后的结果如下: pool-1-thread-1 acquire count=5-1-thread-2 acquire count=4-1-thread-1 release 5-1-thread-2 release 4-1-thread-3 acquire count=7-1-thread-3 release 7
原文地址:http://www.2cto.com/kf/201402/278471.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- java – 将@Controller注入另一个spring bean
- Java语法糖
- java – 禁用apache HTTP Client的日志记录?
- java – 使用getSimpleName()和getName()获取记录器
- java – 泽西:InjectableProvider没有拿起 – 春天
- java – 重定向到另一个端口,保留所有其余的端口
- java.util.ConcurrentModificationException异常;java.util
- 在Java中:如果我将HashMap中的键更改为等于另一个键会发生
- jpa-2.0 – JPA级联持续 – 多对一
- Java字节码检测的替代方案