【java】生产者消费者问题

/**
 * 生产者消费者问题
 */
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class MyTest {

	private static int maxSize = 10;

	public static void main(String[] args) {
		// 存储数据
		LinkedList<Integer> storage = new LinkedList<Integer>();

		// 创建生产者消费者
		Productor p1 = new Productor(storage, "1号生产者");
		Productor p2 = new Productor(storage, "2号生产者");
		Productor p3 = new Productor(storage, "3号生产者");
		Consumer c1 = new Consumer(storage, "1号消费者");
		Consumer c2 = new Consumer(storage, "2号消费者");
		//Consumer c3 = new Consumer(storage, "3号消费者");

		// 创建线程
		Thread t1 = new Thread(p1);
		Thread t2 = new Thread(p2);
		Thread t3 = new Thread(p3);
		Thread t4 = new Thread(c1);
		Thread t5 = new Thread(c2);
		//Thread t6 = new Thread(c3);

		// 开启线程
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		//t6.start();
	}

	/*
	 * 生产者类
	 */
	static class Productor implements Runnable {
		private String name;
		private List<Integer> list;

		private Productor(List<Integer> list, String name) {
			this.list = list;
			this.name = name;
		}

		@Override
		public void run() {
			while (true) {
				synchronized (list) {
					while (list.size() >= maxSize) {
						System.out.println(name + "因空间不足,无法生产,进入等待");
						try {
							list.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					// 这里也可以随机生成一个数字当成是商品
					list.add(1);
					System.out.println(name + "生产了1个商品,现库存:" + list.size());

					// 生产完成后唤醒所有等待线程
					list.notifyAll();
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

	}

	/*
	 * 消费者类
	 */
	static class Consumer implements Runnable {
		private String name;
		private List<Integer> list;

		private Consumer(List<Integer> list, String name) {
			this.list = list;
			this.name = name;
		}

		@Override
		public void run() {
			while (true) {
				synchronized (list) {
					while (list.size() == 0) {
						System.out.println(name + "因余量不足,无法消费,进入等待队列");
						try {
							list.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					// 删除list的第一个元素
					list.remove(0);
					System.out.println(name + "消费了一个商品,现库存:" + list.size());

					// 消费完成后唤醒所有的线程
					list.notifyAll();
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

		}

	}

}
/*注意点:
 * 1、wait外面一般要套用一个while(条件判断)
 * 2、应使用notifyAll而不是notify
 */

 

代码中创建了3个生产者,2个消费者,一直进行生产/消费行为。

并且设置仓储的最大容量为10。

运行结果如下:

1号生产者生产了1个商品,现库存:1
2号生产者生产了1个商品,现库存:2
2号消费者消费了一个商品,现库存:1
3号生产者生产了1个商品,现库存:2
1号消费者消费了一个商品,现库存:1
2号生产者生产了1个商品,现库存:2
1号生产者生产了1个商品,现库存:3
1号消费者消费了一个商品,现库存:2
2号消费者消费了一个商品,现库存:1
3号生产者生产了1个商品,现库存:2
1号生产者生产了1个商品,现库存:3
2号生产者生产了1个商品,现库存:4
3号生产者生产了1个商品,现库存:5
1号消费者消费了一个商品,现库存:4
2号消费者消费了一个商品,现库存:3
1号生产者生产了1个商品,现库存:4
2号生产者生产了1个商品,现库存:5
2号消费者消费了一个商品,现库存:4
3号生产者生产了1个商品,现库存:5
1号消费者消费了一个商品,现库存:4
1号生产者生产了1个商品,现库存:5
2号生产者生产了1个商品,现库存:6
2号消费者消费了一个商品,现库存:5
3号生产者生产了1个商品,现库存:6
1号消费者消费了一个商品,现库存:5
2号生产者生产了1个商品,现库存:6
1号生产者生产了1个商品,现库存:7
1号消费者消费了一个商品,现库存:6
3号生产者生产了1个商品,现库存:7
2号消费者消费了一个商品,现库存:6
2号生产者生产了1个商品,现库存:7
1号生产者生产了1个商品,现库存:8
2号消费者消费了一个商品,现库存:7
3号生产者生产了1个商品,现库存:8
1号消费者消费了一个商品,现库存:7
2号生产者生产了1个商品,现库存:8
1号生产者生产了1个商品,现库存:9
3号生产者生产了1个商品,现库存:10
2号消费者消费了一个商品,现库存:9
1号消费者消费了一个商品,现库存:8
2号生产者生产了1个商品,现库存:9
1号生产者生产了1个商品,现库存:10
2号消费者消费了一个商品,现库存:9
3号生产者生产了1个商品,现库存:10
1号消费者消费了一个商品,现库存:9
2号生产者生产了1个商品,现库存:10
1号生产者因空间不足,无法生产,进入等待
3号生产者因空间不足,无法生产,进入等待
2号消费者消费了一个商品,现库存:9
1号消费者消费了一个商品,现库存:8
3号生产者生产了1个商品,现库存:9
1号生产者生产了1个商品,现库存:10
2号生产者因空间不足,无法生产,进入等待
1号消费者消费了一个商品,现库存:9
2号生产者生产了1个商品,现库存:10
3号生产者因空间不足,无法生产,进入等待
1号生产者因空间不足,无法生产,进入等待
2号消费者消费了一个商品,现库存:9
1号生产者生产了1个商品,现库存:10
3号生产者因空间不足,无法生产,进入等待

..............................

 

注意点分析:

 

1、wait外面一般要套用一个while(条件判断)

如果不加,那么notify过早,线程会陷入等待

如果用if(条件判断),那么线程在判断条件后,进入等待;这时条件已经被更改,该线程被唤醒后会继续执行,而不会重新判断是否符合现在的条件。

详情参考  https://www.jianshu.com/p/e29632593057

2、应使用notifyAll而不是notify

 如果仓储已满,而被唤醒的一直是生产者,那么所有线程都将陷入等待。

 

 

仅供学习过程中的记录,如有错误,请多指教

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值