前一篇文章,使用synchronized和wait、notify/notifyAll结合解决经典的生产者和消费者面试题,详见:Java高并发编程之经典面试题:生产者与消费者线程
这并不是唯一的解决方案,还有更好的,本篇文章讲解如何使用Lock和Condition来实现。
notify/notifyAll的缺陷在于不能指定哪些线程被唤醒,notifyAll的时候,wait状态的生产者和消费者统统被唤醒,而Condition则可以精确指定哪些线程被唤醒。
Condition是条件的意思,就是“在什么条件下做什么事”,Condition提供了两个方法,await和singalAll,功能类似于wait和notifyAll。
代码如下:
public class MyContainer2<T> {
final private LinkedList<T> lists = new LinkedList<>();
/**
* 容器固定容量为10
*/
final private int MAX = 10;
/**
* 容器初始元素个数为0
*/
private int count = 0;
private Lock lock = new ReentrantLock();
private Condition producerCondition = lock.newCondition();
private Condition consumerCondition = lock.newCondition();
/**
* put方法
* @param t
*/
public void put(T t) {
lock.lock();
try {
while (MAX == lists.size()) {
//是生产者就要等待
producerCondition.await();
}
lists.add(t);
++count;
System.out.println(Thread.currentThread().getName() + "进行生产了,当前剩余:" + getCount());
//是消费者就要被唤醒
consumerCondition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* get 方法
* @return
*/
public T get() {
T t = null;
lock.lock();
try {
while (0 == lists.size()) {
//是消费者就要等待
consumerCondition.await();
}
t = lists.removeLast();
--count;
System.out.println(Thread.currentThread().getName() + "进行消费了,当前剩余:" + getCount());
//是生产者就要被唤醒
producerCondition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return t;
}
/**
* getCount方法
* @return
*/
public int getCount() {
return this.count;
}
public static void main(String[] args) {
MyContainer2<String> myContainer2 = new MyContainer2<>();
//创建5个生产者线程
for(int i = 1; i <= 5; i++) {
new Thread(()->{
while(true) {
try {
TimeUnit.SECONDS.sleep(1);
myContainer2.put("");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "p_thread_" + i).start();
}
for(int i = 1; i <= 10; i++) {
new Thread(()->{
while(true) {
try {
TimeUnit.SECONDS.sleep(3);
myContainer2.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "c_thread_" + i).start();
}
}
}
程序执行结果:
p_thread_1进行生产了,当前剩余:1
p_thread_5进行生产了,当前剩余:2
p_thread_4进行生产了,当前剩余:3
p_thread_2进行生产了,当前剩余:4
p_thread_3进行生产了,当前剩余:5
p_thread_1进行生产了,当前剩余:6
p_thread_5进行生产了,当前剩余:7
p_thread_3进行生产了,当前剩余:8
p_thread_4进行生产了,当前剩余:9
p_thread_2进行生产了,当前剩余:10
c_thread_2进行消费了,当前剩余:9
c_thread_1进行消费了,当前剩余:8
c_thread_5进行消费了,当前剩余:7
c_thread_3进行消费了,当前剩余:6
c_thread_4进行消费了,当前剩余:5
c_thread_6进行消费了,当前剩余:4
c_thread_9进行消费了,当前剩余:3
c_thread_7进行消费了,当前剩余:2
c_thread_8进行消费了,当前剩余:1
p_thread_1进行生产了,当前剩余:2
p_thread_3进行生产了,当前剩余:3
p_thread_2进行生产了,当前剩余:4
p_thread_5进行生产了,当前剩余:5
p_thread_4进行生产了,当前剩余:6
c_thread_10进行消费了,当前剩余:5
...
...