Java并发基础-并发工具类(二) (2)

获取许可证
acquire()方法最终调用父类AQS中的acquireSharedInterruptibly方法。

public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) //(1) doAcquireSharedInterruptibly(arg); //(2) }

(1):调用tryAcquireShared,尝试去获取许可证
(2):如果获取失败,则调用doAcquireSharedInterruptibly,将线程加入到等待队列中
tryAcquireShared方法由Semaphore的内部类,同时也是AQS的子类去实现,即NonfairSync和FairSync,下面我们以NonfairSync为例说明其实现。

protected int tryAcquireShared(int acquires) { return nonfairTryAcquireShared(acquires); }

而nonfairTryAcquireShared方法如下:

final int nonfairTryAcquireShared(int acquires) { for (;;) { int available = getState(); //(1) int remaining = available - acquires; //(2) if (remaining < 0 || compareAndSetState(available, remaining)) (3) return remaining; } }

(1):获取state的值,也就是总许可证数量
(2):计算本次申请后,剩余的许可证数量
(3):如果剩余的许可证数量大于0且通过CAS将state的值修改成功后,返回剩余的许可证数量,否则继续循环阻塞。

释放许可证
release()方法的调用最终会调用父类AQS的releaseShared()方法:

public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { //(1) doReleaseShared(); //(2) return true; } return false; }

(1):尝试释放许可证
(2):如果释放许可证成功,则通知阻塞的线程,让其执行
tryReleaseShared方法很简单,基本上是nonfairTryAcquireShared的逆过程,即增加许可证的数量,并通过CAS修改state的值。

protected final boolean tryReleaseShared(int releases) { for (;;) { int current = getState(); int next = current + releases; if (next < current) // overflow throw new Error("Maximum permit count exceeded"); if (compareAndSetState(current, next)) return true; } } BlockingQueue 基本概念

阻塞队列主要是解决如何高效安全传输数据的问题,此外能降低程序耦合度,让代码逻辑更加清晰。
其继承了Queue,并在其基础上支持了两个附加的操作:

当队列为空时,获取元素的线程会阻塞,等待队列变为非空

当队列满时,添加元素的线程会阻塞,等待队列可用

比较典型的使用场景是生产者和消费者。
BlockingQueue根据对于不能立即满足但可能在将来某一时刻可以满足的操作,提供了不同的处理方法,进而导致众多的api操作:



 
Throws exception  
Special value  
Blocks  
Times out  



Insert  
add(e)  
offer(e)  
put(e)  
offer(e, time, unit)  



Remove  
remove()  
poll()  
take()  
poll(time, unit)  



Examine  
element()  
peek()}  
not applicable  
not applicable  


Throws exception:指当阻塞队列满时候,再往队列里插入元素,会抛出IllegalStateException异常。当队列为空时,从队列里获取元素时会抛出NoSuchElementException异常
Special value:插入方法会返回是否成功,成功则返回true。移除方法,则是从队列里拿出一个元素,如果没有则返回null
Blocks:当阻塞队列满时,如果生产者线程往队列里put元素,队列会一直阻塞生产者线程,直到拿到数据,或者响应中断退出。当队列空时,消费者线程试图从队列里take元素,队列也会阻塞消费者线程,直到队列可用。
Time out:当阻塞队列满时,队列会阻塞生产者线程一段时间,如果超过一定的时间,生产者线程就会退出。

整体架构和类图

Java并发包根据不同的结构和功能提供了不同的阻塞队列,整体类图如下:

其中BlockingQueue有如下子类:

ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。

DelayQueue:一个使用优先级队列实现的无界阻塞队列。

PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。

SynchronousQueue:一个不存储元素的阻塞队列。

LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。

其中BlockingDeque有一个子类:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydzdg.html