1.可阻塞的状态依赖操作的结构
acquire lock on object state
while(precondition does not hold){
release lock
wait until precondition might hold
optionally fail if interrupted or timeout expires
reacquire lock
}
perform action
release lock
在生产者-消费者的设计中经常会使用像ArrayBlockingQueue这样的有界缓存。接下来介绍有界缓存的几种实现。
2.有界缓存实现的基类
import org.apache.http.annotation.GuardedBy;
import org.apache.http.annotation.ThreadSafe;
/**
* 有界缓存实现的基类
*/
@ThreadSafe
public abstract class BaseBoundedBuffer<V> {
@GuardedBy("this") private final V[] buf;
@GuardedBy("this") private int tail;
@GuardedBy("this") private int head;
@GuardedBy("this") private int count;
@SuppressWarnings("unchecked")
protected BaseBoundedBuffer(int capacity){
this.buf = (V[])new Object[capacity];
}
protected synchronized final void doPut(V v){//往缓存中放入元素
buf[tail] = v;
if(++tail == buf.length){
tail = 0;
}
++count;
}
protected synchronized final V doTake(){//从缓存中取出元素
V v = buf[head];
buf[head] = null;
if(++head == buf.length){
head = 0;
}
--count;
return v;
}
public synchronized final boolean isFull(){//判断缓存数组中元素是否填满
return count == buf.length;
}
public synchronized final boolean isEmpty(){//判断缓存数组中元素是否为空
return count == 0;
}
}
3.将前提条件的失败传递给调用者
下面是一个简单的有界缓存实现,put和take方法都进行了同步以确保对缓存状态的独占访问,因为这两个方法在访问缓存时都采用“先检查,再运行”的逻辑策略。
当不满足前提条件时,有界缓存不会执行相应的操作。
简单的有界缓存实现
@ThreadSafe
public class GrumpyBoundedBuffer<V> extends BaseBoundedBuffer<V>{
protected GrumpyBoundedBuffer(int capacity) {
super(capacity);
}
public synchronized void put(V v) throws BufferFullException{
if(isFull()){
throw new BufferFullException();
}
doPut(v);
}
public synchronized V take() throws BufferNullException{
if(isEmpty()){
throw new BufferNullException();
}
doTake();
}
}
4.调用GrumpyBoundedBuffer的代码
while(true){
try{
V item = buffer.take();
//对item执行一些操作
break;
}catch(BufferEmptyException e){ Thread.sleep(SlEEP_GRANULARITY);
}}
5.通过轮询与休眠来实现简单的阻塞
使用简单阻塞实现的有界缓存
@ThreadSafe
public class SleepyBoundedBuffer<V> extends BaseBoundedBuffer<V>{
protected SleepyBoundedBuffer(int capacity) {
super(capacity);
}
public void put(V v) throws InterruptedException{
while(true){
synchronized(this){
if(!isFull()){
doPut(v);
return;
}
}
Thread.sleep(SLEEP_GRANULARITY);
}
}
public V take() throws InterruptedException{
while(true){
synchronized(this){
if(!isEmpty()){
return doTake();
}
}
Thread.sleep(SLEEP_GRANULARITY);
}
}
}
6.条件队列
import org.apache.http.annotation.ThreadSafe;
/**
* 使用条件队列实现的有界循环
* @Class_Name: BoundedBuffer
*/
@ThreadSafe
public class BoundedBuffer<V> extends BaseBoundedBuffer<V> {
//条件谓词:not-full(!isFull())
//条件谓词:not-empty(!isEmpty())
protected BoundedBuffer(int capacity) {
super(capacity);
}
//阻塞并直到:not-null
public synchronized void put(V v) throws InterruptedException{
while(isFull()){
wait();
}
doPut(v);
notifyAll();
}
//阻塞并直到:not-empty
public synchronized V take() throws InterruptedException{
while(isEmpty()){
wait();
}
V v = doTake();
notifyAll();
return v;
}
}