Condition接口
目的:替代传统的Object的wait()、notify()。
相较于Object的wait()、notify(),使用Condition的await()、signal()来实现线程间的协作更加的安全,效率也更高。
使用wait、notify的前提是必须获取到监视器对象,否则会抛异常。因为wait会释放锁,释放锁的前提肯定是必须先拥有锁。
和wait、notify一样,使用await、signal的前提也是必须先获取到锁,否则也会抛异常。
如下:
public static void main(String[] args) throws InterruptedException {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
condition.await();
}
Exception in thread "main" java.lang.IllegalMonitorStateException
Condition需要与Lock配合使用!
API
-
void await()
线程进入等待状态。 -
void awaitUninterruptibly()
线程进入等待状态,不理会中断。 -
long awaitNanos(long nanosTimeout)
线程等待,支持纳秒级的超时,返回剩余时间。 -
boolean awaitUntil(Date deadline)
线程等待,直到被通知,中断,或到达deadline时间。 -
void signal()
唤醒一个等待在Condition上的线程。 -
void signalAll()
唤醒所有等待在Condition上的线程。
使用示例
Condition内部维护了一个等待队列,当线程调用condition.await()时,会将当前线程封装成一个Node并添加到队列中,然后释放锁,供其他线程竞争。
调用condition.signal()时,会唤醒等待队列中等待时间最长的节点(头节点),并将该节点移出队列,该节点中的线程会继续竞争锁,执行逻辑代码。
经典的消费者生产者
public class ConditionDemo {
//最大库存数
private final int MAX_COUNT = 10;
//库存数
private volatile int goodsCount = 0;
//随机决定线程休眠时间
private Random random = new Random();
//锁
private Lock lock = new ReentrantLock();
//生产者condition
private Condition producerCondition = lock.newCondition();
//消费者condition
private Condition consumerCondition = lock.newCondition();
public class Producer extends Thread {
volatile boolean flag = true;
@Override
public void run() {
while (flag) {
lock.lock();
try {
if (goodsCount >= MAX_COUNT) {
//System.err.println("库存满.");
//库存满 停止生产 通知消费者消费
consumerCondition.signalAll();
producerCondition.await();
}
SleepUtil.sleep(random.nextInt(500));
System.out.println("生产:"+(++goodsCount));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
private class Consumer extends Thread{
@Override
public void run() {
while (true) {
lock.lock();
try {
if (goodsCount <= 0) {
//没有库存,停止消费 通知生产者生产
//System.err.println("没有库存了..");
producerCondition.signalAll();
consumerCondition.await();
}else {
SleepUtil.sleep(random.nextInt(500));
System.out.println("消费:" + (--goodsCount));
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
public static void main(String[] args) {
ConditionDemo demo = new ConditionDemo();
//创建一个生产者
demo.new Producer().start();
//创建5个消费者
for (int i = 0; i < 5; i++) {
demo.new Consumer().start();
}
}
}