package com.wkcto.chapter07.producerconsumer.p3;
/**
* 生產(chǎn)者消費者設(shè)計模式
* 在企業(yè)中有一組工人負責生產(chǎn), 有一組員工負責銷售, 他們都可以同時進行工作
* 工人生產(chǎn)的產(chǎn)品存儲到倉庫中, 如果倉庫已滿, 需要等待銷售人員銷售后,再繼續(xù)生產(chǎn)
* 銷售人員從倉庫中銷售產(chǎn)品, 如果倉庫已空, 需要等待生產(chǎn)者生產(chǎn)了產(chǎn)品后再繼續(xù)銷售
* 工人在生產(chǎn)產(chǎn)品期間, 還沒有完全生產(chǎn)完, 不能銷售
* 產(chǎn)品在銷售過程中, 也不能再存儲到倉庫中
*
* 定義線程模擬不同的生產(chǎn) 者, 定義線程模擬不同的消費者, 不管是生產(chǎn)者還是消費者都需要借助倉庫中轉(zhuǎn)
*
* @author 蛙課網(wǎng)
*
*/
public class Test01 {
public static void main(String[] args) {
//創(chuàng)建倉庫對象
MyStorage storage = new MyStorage();
//創(chuàng)建三個生產(chǎn)者
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();
//創(chuàng)建三個消費者
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 蛙課網(wǎng)
*
*/
import java.util.LinkedList;
public class MyStorage {
private LinkedList<String> list = new LinkedList<>(); //作為倉庫,保存產(chǎn)品
private static final int MAX = 100; //定義常量,表示倉庫的最大容量
//向倉庫中存儲產(chǎn)品 , 在存儲產(chǎn)品期間不允許消費
public synchronized void store( String product) {
//如果倉庫已滿 , 需要等待消費者消費
while ( list.size() >= MAX) {
try {
this.wait(); //wait()/nofity()方法必須在同步代碼塊中,由鎖對象調(diào)用
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//存儲產(chǎn)品
list.offer(product);
System.out.println("++++++++++++++" + Thread.currentThread().getName() + "存儲了" + product + "后,倉庫容量:" + list.size());
//通知消費者消費
this.notify();
}
//從倉庫中取產(chǎn)品 , 生產(chǎn)者需要等消費者取完產(chǎn)品后才能再存儲產(chǎn)品
public synchronized void get() {
//如果倉庫已空, 消費者需要等待
while ( list.size() <= 0 ) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//取產(chǎn)品
System.out.println( Thread.currentThread().getName() + "取了產(chǎn)品" + list.poll()+ "后,倉庫容量:" + list.size());
//通知生產(chǎn)者生產(chǎn)
this.notifyAll();
}
}
package com.wkcto.chapter07.producerconsumer.p3;
import java.util.Random;
/**
* 定義生產(chǎn)者線程
* 生產(chǎn)了產(chǎn)品存儲到倉庫中
* @author 蛙課網(wǎng)
*
*/
public class Producer extends Thread {
MyStorage storate; //倉庫
public Producer(MyStorage storate) {
super();
this.storate = storate;
}
@Override
public void run() {
//不斷生產(chǎn)產(chǎn)品
for( int i = 1; i <= 100; i++){
String product = "product:" + new Random().nextInt(200);
storate.store( product );
}
}
}
package com.wkcto.chapter07.producerconsumer.p3;
/**
* 定義消費者線程
* 消費者從倉庫中取產(chǎn)品
* @author 蛙課網(wǎng)
*
*/
public class Consumer extends Thread {
MyStorage storate; //倉庫
public Consumer(MyStorage storate) {
super();
this.storate = storate;
}
@Override
public void run() {
//不斷消費產(chǎn)品
for( int i = 1; i <= 100; i++){
storate.get();
}
}
}
練習:
package com.wkcto.chapter07.producerconsumer.p2;
/**
* 創(chuàng)建兩個線程,一個線程打印奇數(shù),一個線程打印偶數(shù),實現(xiàn)兩個線程的交替打印
* 線程1 : 1
* 線程2 : 2
* 線程1 : 3
* 線程2 : 4
* 線程1 : 5
* 線程2 : 6
* 線程1 : 7
* @author 蛙課網(wǎng)
*
*/
public class Test {
public static void main(String[] args) {
PrintNum printNum = new PrintNum();
//創(chuàng)建線程打印奇數(shù)
new Thread(new Runnable() {
@Override
public void run() {
while( true ){
printNum.printOdd();
}
}
}).start();
//創(chuàng)建線程打印偶數(shù)
new Thread(new Runnable() {
@Override
public void run() {
while( true ){
printNum.printEven();
}
}
}).start();
}
}
package com.wkcto.chapter07.producerconsumer.p2;
/**
* 定義一個打印奇數(shù)和偶數(shù)的類
* @author 蛙課網(wǎng)
*
*/
public class PrintNum {
private int num = 1; //保存要打印的數(shù)
//打印奇數(shù)
public synchronized void printOdd() {
//當num是偶數(shù)時, 需要等待
while( num % 2 == 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果是奇數(shù)就打印
System.out.println( Thread.currentThread().getName() + " : " + num );
num++; //變?yōu)榕紨?shù)
//通知打印偶數(shù)
this.notify();
}
//打印偶數(shù)
public synchronized void printEven() {
//當num是奇數(shù)時, 需要等待
while( num % 2 != 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果是偶數(shù)就打印
System.out.println( Thread.currentThread().getName() + " : " + num );
num++; //變?yōu)槠鏀?shù)
//通知打印奇數(shù)
this.notify();
}
}