生产者消费者实例:
public class ProductorCustom<T> {
private final ReentrantLock lock = new ReentrantLock();
private Condition putButFull = lock.newCondition();
private Condition tackButEmpty = lock.newCondition();
private int head, tail, count;
private final T[] items;
public ProductorCustom() {
this(10);
}
public ProductorCustom(int maxSize) {
items = (T[]) new Object[maxSize];
}
public void put(T item) throws InterruptedException {
lock.lock();
try {
while(count == items.length) {
putButFull.await();
}
items[tail] = item;
if (++tail == items.length) {
tail = 0;
}
++count;
tackButEmpty.signal();
}
finally {
lock.unlock();
}
}
public T take() throws InterruptedException {
lock.lock();
try {
while (count == 0) {
tackButEmpty.await();
}
T item = items[head];
if (++head == items.length) {
head = 0;
}
--count;
putButFull.signal();
return item;
}
finally {
lock.unlock();
}
}
}
在没有Lock之前,我们使用synchronized来控制同步,配合Object的wait()、notify()系列方法可以实现等待/通知模式。在Java SE5后,Java提供了Lock接口,相对于Synchronized而言,Lock提供了条件Condition,对线程的等待、唤醒操作更加详细和灵活。如上面实例Condition依赖Lock对象,在调用时一定要先获得Condition对象关联的锁。
// 当前线程直到被通知/中断前一直处于等待状态,如果当前线程从await方法返回,则表明线程已经获取到了Condition对象所对应的锁
void await() throws InterruptedException;
//当前线程进入等待状态直到被通知,对中断不敏感
void awaitUninterruptibly();
// 当前线程进入等待状态直到被通知,中断或超时,返回值表示剩余时间,如果为0或负数即超时
long awaitNanos(long nanosTimeout) throws InterruptedException;
// 当前线程进入等待状态直到被通知,中断或超时,不同于上一个方法时间为纳秒,该方法可以指定时间的单位,到时间返回false其它返回true
boolean await(long time, TimeUnit unit) throws InterruptedException;
// 当前线程进入等待状态直到被通知,中断或到某个时间。没到指定时间被通知中断返回true,否则表示到了指定时间返回false
boolean awaitUntil(Date deadline) throws InterruptedException;
// 唤醒一个等待在Condition上的线程,该线程从等待方法返回前必须获得于Condition相关联的锁
void signal();
// 唤醒所有等待在Condition上的线程,能够从等待方法返回的线程必须获得与Condition相关联的锁
void signalAll();
ReentrantLock 的newCondition():
public Condition newCondition() {
return sync.newCondition();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
最终调用的是AQS中的内部类ConditionObject,它实现了Condition接口。Condition必须被绑定到一个独占锁上使用
概述
AQS有一个同步队列;ConditionObject维护了一个等待队列,二者节点的类型都是AQS.Node。Condition的等待队列包含线程引用,当调用await方法,构建成节点加入到等待队列,释放锁。
不同:1,