Java面向对象
Java异常
Java数组
Java常用类
Java集合
Java IO流
Java线程
Java反射
Socket编程
Java注解开发
Java GoF设计模式
HashMap
Java内存模型
Java线性表

Java设计模式之生产者消费者模式

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();
	}
	
}