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;
	}

}