在讲 synchronized 时候,我们使用 synchronized 实现了生产者消费者问题,本篇我们再使用 Lock 和 Condition 来实现。
【Java并发编程】synchronized(一):生产者消费者问题
对比两种方式,Condition 的方式可以更加精确的指定哪些线程被唤醒
public class MyContainer03<T> {
// 容器
LinkedList<T> list = new LinkedList<>();
// 最大容量
final static int MAX_SIZE = 10;
// 锁
ReentrantLock lock = new ReentrantLock();
// 生产者条件队列(已满)
Condition producer = lock.newCondition();
// 消费者条件队列(已空)
Condition consumer = lock.newCondition();
void put(T t){
try {
// 加锁
lock.lock();
// while 重复校验
while (this.list.size() == MAX_SIZE){
// 进入生产者条件队列
producer.await();
}
// 生产
this.list.add(t);
// 唤醒所有消费者
// 注:这里就不会再唤醒生产者了
consumer.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 解锁
lock.unlock();
}
}
T get(){
T t = null;
try {
// 加锁
lock.lock();
// while 重复校验
while (this.list.size() == 0){
// 进入消费者条件队列
consumer.await();
}
// 消费
t = list.removeFirst();
// 唤醒消费者
producer.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 放锁
lock.unlock();
}
return t;
}
public static void main(String[] args) {
MyContainer03<String> container02 = new MyContainer03<>();
for(int i=0;i<5;i++){
new Thread(()->{
System.out.println("消费-"+Thread.currentThread().getName()+"-"+container02.get());
},"xf"+i+1).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=0;i<2;i++){
new Thread(()->{
for(int j=0;j<5;j++){
container02.put(Thread.currentThread().getName()+"制造"+j);
System.out.println("生产-"+Thread.currentThread().getName()+"制造"+j);
}
},"sc"+(i+1)).start();
}
}
}