一、Condition的介绍
Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,阻塞队列实际上是使用了Condition来模拟线程间协作。
- Condition是个接口,基本的方法就是await()和signal()方法;
- Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
- 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
Conditon中的await()对应Object的wait();
Condition中的signal()对应Object的notify();
Condition中的signalAll()对应Object的notifyAll()。
二、实现生产消费者模型
public class About_Condition {
public static void main(String[] args) {
Condition_exam condition_exam = new Condition_exam();
for(int i = 0; i < 3; i++) {
new Thread(() -> {
condition_exam.product();
}).start();
}
for(int i = 0; i < 5; i++) {
new Thread(() -> {
condition_exam.comsume();
}).start();
}
for(int i = 0; i < 2; i++ ) {
new Thread(() -> {
condition_exam.product();
}).start();
}
}
}
class Condition_exam {
private PriorityQueue<Integer> queue = new PriorityQueue<>();
private int capacity = 5;
private Lock lock = new ReentrantLock();
private Condition notEmpty = lock.newCondition();
private Condition notFull = lock.newCondition();
public void comsume() {
lock.lock();
try {
while (queue.size() == 0) {
notEmpty.await();
}
Thread.sleep(600);
queue.remove();
notFull.signal(); // 唤醒那些因为队列满而睡眠的线程
System.out.println("Comsumer comsumed 1." + " now the size is : " + queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void product() {
lock.lock();
try {
while (queue.size() == capacity) {
notFull.await();
}
Thread.sleep(600);
queue.add(1);
notEmpty.signal(); // 唤醒那些因为队列为空睡眠的线程
System.out.println("Productor producted 1. " + " now the size is : " + queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
结果输出:
Productor producted 1. now the size is : 1
Productor producted 1. now the size is : 2
Productor producted 1. now the size is : 3
Comsumer comsumed 1. now the size is : 2
Comsumer comsumed 1. now the size is : 1
Comsumer comsumed 1. now the size is : 0
Productor producted 1. now the size is : 1
Productor producted 1. now the size is : 2
Comsumer comsumed 1. now the size is : 1
Comsumer comsumed 1. now the size is : 0
代码对比阻塞队列 BlockingQueue 源码:
ArrayBlockingQueue 中的 take() 方法。
// 对应消费者
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
ArrayBlockingQueue 中的 put() 方法。
// 对应生产者
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
更多关于Condition。
参考博客:java condition使用及分析