java实现生产者和消费者模式

134 阅读2分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路.

  1. 什么是“生产者和消费者模式”? 生产线程负责生产,消费线程负责消费。 这是一种特殊的业务需求,在这种特殊的情况下需要使用wait方法和notify方法。
  2. wait和notify方法不是线程对象的方法,是普通java对象都有的方法。
  3. wait方法和notify方法建立在线程同步的基础之上。因为多线程要同时操作一个仓库。有线程安全问题。
  4. wait方法作用: o.wait()让正在o对象上活动的线程t进入等待状态,并且释放掉t线程之前占有的o对象的锁。
  5. notify方法作用: o.notify()让正在o对象上等待的线程唤醒,只是通知,不会释放o对象上之前占有的锁。
  6. 模拟这祥一个需求: 仓库我们采用List集合。 List集合中假设只能存储1个元素。1个元素就表示仓库满了。 如果List集合中元素个数是0,就表示仓厍空了。 必须做到这种效果:生产1个消费1个。

实现

import java.util.ArrayList;
import java.util.List;

public class Test {

	public static void main(String[] args) {
		List list = new ArrayList();
		Thread t1 = new Procuder(list);
		Thread t2 = new Consumer(list);

		t1.setName("t1");
		t2.setName("t2");

		t1.start();
		t2.start();
	}
}

// 生产者类
class Procuder extends Thread {

	private List list;

	public Procuder(List list) {
		this.list = list;
	}

	@Override
	public void run() {
		// 死循环,表示一直生产
		while (true) {
			// 给仓库对象加锁
			synchronized (list) {
				// 大于0,说明仓库中已经有1一个元素了
				if (list.size() > 0) {
					try {
						// 让当前线程进入等待状态,并释放Producer之前占有的list对象的锁,使得下面的Consumer可以获得list的锁继续执行
						list.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				try {
					sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				// 程序能执行到这里,说明仓库是空的,应该生产一个商品
				Object obj = new Object();
				list.add(obj);
				System.out.println(Thread.currentThread().getName() + "生产" + obj);
				// 唤醒调用了list的wait方法的线程,注意当前有synchronized限制,所以消费者需要等到生产者出了synchronized代码块后才会执行
				list.notifyAll();
			}
		}
	}
}

// 消费者类类
class Consumer extends Thread {

	private List list;

	public Consumer(List list) {
		this.list = list;
	}

	@Override
	public void run() {
		// 死循环,表示一直消费
		while (true) {
			// 给仓库对象加锁
			synchronized (list) {
				// 等于0,说明仓库中没有元素可以消费
				if (list.size() == 0) {
					try {
						// 让当前线程进入等待状态,并释放Consumer之前占有的list对象的锁,使得上面的Procuder可以获得list对象的锁继续执行
						list.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				try {
					sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				// 程序能执行到这里,说明仓库是有元素的,应该消费一个商品
				Object obj = list.remove(0);
				System.out.println(Thread.currentThread().getName() + "消费" + obj);
				// 唤醒调用了list的wait方法的线程,注意当前有synchronized限制,所以消费者需要等到生产者出了synchronized代码块后才会执行
				list.notifyAll();
			}
		}
	}
}