package com.wkcto.chapter07.producerconsumer.p3;
/**
* 生产者消费者设计模式
* 在企业中有一组工人负责生产, 有一组员工负责销售, 他们都可以同时进行工作
* 工人生产的产品存储到仓库中, 如果仓库已满, 需要等待销售人员销售后,再继续生产
* 销售人员从仓库中销售产品, 如果仓库已空, 需要等待生产者生产了产品后再继续销售
* 工人在生产产品期间, 还没有完全生产完, 不能销售
* 产品在销售过程中, 也不能再存储到仓库中
*
* 定义线程模拟不同的生产 者, 定义线程模拟不同的消费者, 不管是生产者还是消费者都需要借助仓库中转
*
* @author 蛙课网
*
*/
public class Test01 {
public static void main(String[] args) {
//创建仓库对象
MyStorage storage = new MyStorage();
//创建三个生产者
Producer lisi = new Producer(storage);
Producer feifei = new Producer(storage);
Producer xiaoming = new Producer(storage);
lisi.setName("lisi");
feifei.setName("feifei");
xiaoming.setName("xiaoming");
lisi.start();
feifei.start();
xiaoming.start();
//创建三个消费者
Consumer yong = new Consumer(storage);
Consumer zhang = new Consumer(storage);
Consumer du = new Consumer(storage);
yong.setName("yong");;
zhang.setName("zhang");
du.setName("du");
yong.start();
zhang.start();
du.start();
}
}
package com.wkcto.chapter07.producerconsumer.p3;
/**
* 仓库类
* @author 蛙课网
*
*/
import java.util.LinkedList;
public class MyStorage {
private LinkedList<String> list = new LinkedList<>(); //作为仓库,保存产品
private static final int MAX = 100; //定义常量,表示仓库的最大容量
//向仓库中存储产品 , 在存储产品期间不允许消费
public synchronized void store( String product) {
//如果仓库已满 , 需要等待消费者消费
while ( list.size() >= MAX) {
try {
this.wait(); //wait()/nofity()方法必须在同步代码块中,由锁对象调用
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//存储产品
list.offer(product);
System.out.println("++++++++++++++" + Thread.currentThread().getName() + "存储了" + product + "后,仓库容量:" + list.size());
//通知消费者消费
this.notify();
}
//从仓库中取产品 , 生产者需要等消费者取完产品后才能再存储产品
public synchronized void get() {
//如果仓库已空, 消费者需要等待
while ( list.size() <= 0 ) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//取产品
System.out.println( Thread.currentThread().getName() + "取了产品" + list.poll()+ "后,仓库容量:" + list.size());
//通知生产者生产
this.notifyAll();
}
}
package com.wkcto.chapter07.producerconsumer.p3;
import java.util.Random;
/**
* 定义生产者线程
* 生产了产品存储到仓库中
* @author 蛙课网
*
*/
public class Producer extends Thread {
MyStorage storate; //仓库
public Producer(MyStorage storate) {
super();
this.storate = storate;
}
@Override
public void run() {
//不断生产产品
for( int i = 1; i <= 100; i++){
String product = "product:" + new Random().nextInt(200);
storate.store( product );
}
}
}
package com.wkcto.chapter07.producerconsumer.p3;
/**
* 定义消费者线程
* 消费者从仓库中取产品
* @author 蛙课网
*
*/
public class Consumer extends Thread {
MyStorage storate; //仓库
public Consumer(MyStorage storate) {
super();
this.storate = storate;
}
@Override
public void run() {
//不断消费产品
for( int i = 1; i <= 100; i++){
storate.get();
}
}
}
练习:
package com.wkcto.chapter07.producerconsumer.p2;
/**
* 创建两个线程,一个线程打印奇数,一个线程打印偶数,实现两个线程的交替打印
* 线程1 : 1
* 线程2 : 2
* 线程1 : 3
* 线程2 : 4
* 线程1 : 5
* 线程2 : 6
* 线程1 : 7
* @author 蛙课网
*
*/
public class Test {
public static void main(String[] args) {
PrintNum printNum = new PrintNum();
//创建线程打印奇数
new Thread(new Runnable() {
@Override
public void run() {
while( true ){
printNum.printOdd();
}
}
}).start();
//创建线程打印偶数
new Thread(new Runnable() {
@Override
public void run() {
while( true ){
printNum.printEven();
}
}
}).start();
}
}
package com.wkcto.chapter07.producerconsumer.p2;
/**
* 定义一个打印奇数和偶数的类
* @author 蛙课网
*
*/
public class PrintNum {
private int num = 1; //保存要打印的数
//打印奇数
public synchronized void printOdd() {
//当num是偶数时, 需要等待
while( num % 2 == 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果是奇数就打印
System.out.println( Thread.currentThread().getName() + " : " + num );
num++; //变为偶数
//通知打印偶数
this.notify();
}
//打印偶数
public synchronized void printEven() {
//当num是奇数时, 需要等待
while( num % 2 != 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果是偶数就打印
System.out.println( Thread.currentThread().getName() + " : " + num );
num++; //变为奇数
//通知打印奇数
this.notify();
}
}