/**
* 生产者消费者问题
*/
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
如果仓储已满,而被唤醒的一直是生产者,那么所有线程都将陷入等待。
仅供学习过程中的记录,如有错误,请多指教