多线程(Java)等待唤醒机制之多生产者与多消费者示例

多线程之多生产者与多消费者

在上一篇文章里,我们介绍了线程的等待唤醒机制,并用单生产者和单消费者来演示了notify() 和 wait() 等待唤醒相关方法。

这篇文章我们来通过多生产者和多消费者来演示notifyAll()的方法。

多线程(Java)等待唤醒机制之多生产者与多消费者示例_第1张图片

我们要实现的效果原理为上图,我们有两个生产者线程,在isProduce = false时,在P1和P2线程中随机一条线程来进行生产商品,生产完毕后,再在C1和C2消费者线程中随机唤醒一条线程来消费商品。

 

class Resource {
	private boolean isProduced = false;
	private int count;

	public Resource() {
		super();
	}

	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 + "商品");
	}
}

 

class Producer extends Thread{
	private Resource resource;

	public Producer(Resource resource) {
		super();
		this.resource = resource;
	}
	
	@Override
	public void run() {
		synchronized (resource) {
			while(true) {
				if(resource.isProduced()) {
					try {
						resource.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}else {
					resource.produce();
					resource.setProduced(true);
					resource.notifyAll();
				}
			}
		}
	}
}
class Consumer extends Thread{
	private Resource resource;

	public Consumer(Resource resource) {
		super();
		this.resource = resource;
	}
	
	@Override
	public void run() {
		while(true) {
			synchronized (resource) {
				if(!resource.isProduced()) {
					try {
						resource.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}else {
					resource.consume();
					resource.setProduced(false);
					resource.notifyAll();
				}
			}
		}
	}
}

 

package com.evan.multi_producer_consumer;

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)等待唤醒机制之多生产者与多消费者示例_第2张图片

运行效果如上图。

 

我们发现Thread - 0 和 Thread - 1为生产者线程,Thread - 2 和 Thread - 3 为消费者线程。

在Producer.class的run方法中,我们判断如果isProduced == true,那么我们自己就睡眠,如果isProduced == false,那么我们就生产一个商品,生产完之后,我们睡眠,睡眠之前调用notifyAll()。

在Consumer.class的run方法中,我们判断如果isProduced == false, 那么我们自己就睡眠,如果isProduced == true,那么我们就消费一个商品,消费完之后,我们睡眠,睡眠之前调用notifyAll()。

这里和单生产者单消费者文章里唯一不同的就是将notify()方法替换为了notifyAll()方法。


我们在使用Object.wait() 时,是将当前线程睡眠在了这个对象背后的池子里,而这个池子里可以睡眠N多条线程。

当我们在调用notify()时,他的工作原理是在池子里随机唤醒一条线程。

而我们现在有4条线程,p1 p2 c1 c2,假设p1生产完毕,需要唤醒p2 c1 c2中的消费者线程,那么因为notify是随机的,我们无法保证唤醒的是c1 和 c2中的一条,所以我们需要使用notifyAll() 线程,来将这3条线程都唤醒,那么p2就算唤醒了,当判断到标记isProduced = true时,也会自动睡眠,从而保证了消费者阵营中,有一条线程去消费该商品。

你可能感兴趣的:(Java)