正文
u 若一个方法不需要等待某个条件成立,则称为该方法是完全的。如从空队列中删除元素时,可以立刻抛出返回错误。因此当生产者或消费者线程有比等待调用生效还要好的其他事情可处理时,完全化的操作接口非常适用。
u 若一个方法的调用需要等待某个条件成立,则称为该方法为部分的。如从空队列中删除元素的操作会被阻塞,直到池中有可用元素才返回。当生产者或消费者线程除了等待调用生效以外,没有其他更好的事情可做时,部分化的操作接口非常适用。
u 若一个方法需要等待另一个方法与他的调用相重叠,则称该方法为同步的。如一个向队列中添加元素的方法调用会被阻塞,直到被添加的元素被另一个线程的方法取用。当生产者和消费者线程之间需要进行通信或严格同步时,同步化的操作接口非常适用。
池可以基于各种数据结构来实现,进而实现各种公平策略。如基于队列的先进先出的池,基于栈的后进先出的池,以及其他的一些若公平性原则的池。但无论如何实现池的公平策略,都要解决在高并行环境下高性能、低消耗、无干扰的交互,事实上要达到这样级别的并行性并非易事。下面我们将分为部分有界队列池、完全无界队列池、以及同步化队列池几种情况,来探讨并行环境下基于队列的池,如何实现高级别并行的相关技术细节。
2 部分有界队列
下面的代码基于链表实现有界队列,并且使用Java5之后提供的原子变量、可重入锁、条件变量等手段实现并行环境下的线程交互控制。通过原子变量、可重入锁、条件变量等技术手段,可以实现更加细化的锁粒度的控制,相比之前Java提供的同步锁机制,这样实现能够实现更加高效的线程交互和更小的总体消耗。
首先定义基于链表的队列的元素节点对象:
publicclassBoundedNode {
public Object value;
public BoundedNode next;
public BoundedNode(Object x){
value=x;
next=null;
}
}
然后定义队列的主体实现,其中主要包括:入队和出对操作。
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
publicclassBoundedQueue {
ReentrantLock enqlock,deqlock;
Condition notempty,notfull;
AtomicInteger size;
BoundedNode head,tail;//队列头哨兵和尾哨兵
intcapacity;
publicBoundedQueue(intcapacity){
this.capacity=capacity;
head=newBoundedNode(null);
tail=head;