多线程(Java)利用Lock接口实现多生产者多消费者

利用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();
	}

}

多线程(Java)利用Lock接口实现多生产者多消费者_第1张图片 

 

 我们在Resource.class中,我们定义了一个Lock,和两个Condition对象,而这两个Condition对象,则从属于此Lock对象,因此我们可以用这两个Condition对象来区分生产者和消费者线程阵营,从而避免notify()方法唤醒线程的随机性而降低的效率。

 

 

你可能感兴趣的:(Java)