利用Lock接口实现多生产者多消费者
在上一篇文章中,我们介绍了等待唤醒机制里的notifyAll方法,并编写了多生产者和多消费者的代码示例。
但有一点,因为我们在使用wait()方法后,将4条线程睡眠,我们在生产完毕后,需要使用notifyAll()方法,来唤醒所有的线程,因为notify()方法是唤醒当前对象池子里随机一条线程,我们无法保证唤醒消费者线程的其中一个。
本篇文章,我们介绍利用Lock接口,来实现等待唤醒机制,并且可以将不同阵营的线程加以区分,以避免notify()方法随机性唤醒而造成的低效率问题。
class Resource{
private int count = 0;
private boolean isProduced = false;
private Lock lock = new ReentrantLock();
private Condition producerCondition = lock.newCondition();
private Condition consumerCondition = lock.newCondition();
public boolean isProduced() {
return isProduced;
}
public void setProduced(boolean isProduced) {
this.isProduced = isProduced;
}
public void produce() {
count++;
System.out.println("生产者线程---" + Thread.currentThread().getName() + "生产商品" + count);
}
public void consume() {
System.out.println("消费者线程------" + Thread.currentThread().getName() + "消费商品" + count);
}
public Lock getLock() {
return lock;
}
public Condition getProducerCondition() {
return producerCondition;
}
public Condition getConsumerCondition() {
return consumerCondition;
}
}
class Producer extends Thread{
private Resource resource;
public Producer(Resource resource) {
super();
this.resource = resource;
}
@Override
public void run() {
while(true) {
try {
resource.getLock().lock();
if(resource.isProduced()) {
resource.getProducerCondition().await();
}else {
resource.produce();
resource.setProduced(true);
resource.getConsumerCondition().signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
resource.getLock().unlock();
}
}
}
}
class Consumer extends Thread{
private Resource resource;
public Consumer(Resource resource) {
super();
this.resource = resource;
}
@Override
public void run() {
while(true) {
try {
resource.getLock().lock();
if(!resource.isProduced()) {
resource.getConsumerCondition().await();
}else {
resource.consume();
resource.setProduced(false);
resource.getProducerCondition().signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
resource.getLock().unlock();
}
}
}
}
package com.evan.lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo {
public static void main(String[] args) {
Resource resource = new Resource();
Producer p1 = new Producer(resource);
Producer p2 = new Producer(resource);
Consumer c1 = new Consumer(resource);
Consumer c2 = new Consumer(resource);
p1.start();
p2.start();
c1.start();
c2.start();
}
}
我们在Resource.class中,我们定义了一个Lock,和两个Condition对象,而这两个Condition对象,则从属于此Lock对象,因此我们可以用这两个Condition对象来区分生产者和消费者线程阵营,从而避免notify()方法唤醒线程的随机性而降低的效率。