Java 多线程实现生产者消费者问题(wait/notify)

本文参考网上一些例子,使用synchronized及对象的wait/notify方法实现。

首先定义3个类,一个是容器类,属性有容器最大容量和当前容量;

另外两个分别是生产者和消费者类,二者分别有生产方法和消费方法(均在各自的run方法中实现,实际上最好抽离出来成为一个单独的方法)


package test3;

class Container{
	public int max; //定义容器最大容量
	public int currentNum;//定义容器当前容量
	
	public Container(int max){
		this.max = max;
		currentNum = 0;
	}
}
class Producer implements Runnable{
	public Container con;
	public Producer(Container con){
		this.con = con;
	}
	public void run(){
		while(true){//有无数个苹果
			synchronized(con){
				if(con.currentNum < con.max){//若当前容器不满,则可以生产
					con.notify();//生产完则通知并释放锁
					con.currentNum++;
					System.out.println(" 生产者正在生产...+1, 当前产品数:"+con.currentNum);
				}else if(con.currentNum == con.max){//
					System.out.println("箱子已经饱和,生产者停止生产,正在等待消费...");	
					try {
						con.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}//if else if				
			}//syn	执行完同步块	释放锁,输出结果中连续出现两次生产者是因为:释放锁后,若没有等待线程,则还是先执行到哪个线程的同步块就执行它
			
			try {
				Thread.sleep(100);//调节生产者频率,过快容易猝死~~
			} catch (InterruptedException e) {
				e.printStackTrace();
			}//try
		}//while
	}
}

class Consumer implements Runnable{
	public Container con;
	public Consumer(Container con){
		this.con = con;
	}
	public void run(){
		while(true){
			synchronized(con){
				if(con.currentNum > 0 ){
					con.notify();
					con.currentNum--;
					System.out.println(" 消费者正在消费...-1, 当前产品数:"+con.currentNum);
				}else if(con.currentNum == 0){
					System.out.println("箱子已经空了,消费者停止消费,正在等待生产...");	
					try {
						con.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}//else if				
			}//syn		
			
			try {
				Thread.sleep(140);//调节消费者频率,过快容易撑死~~
			} catch (InterruptedException e) {
				e.printStackTrace();
			}//try
		}//while
	}// run
}
public class TestProducerConsumer{
	public static void main(String args[]){
		Container container = new Container(5);//定义箱子最大容量,此处为5
		Producer producer =  new Producer(container);//箱子中的苹果数要同步,所以将箱子对象引用作为形参传给生产者和消费者
		Consumer consumer = new Consumer(container);//
		
		new Thread(producer, "producer").start();//启动生产消费模式
		new Thread(consumer, "consumer").start();
	}
}

程序输出:

 生产者正在生产...+1, 当前产品数:1
 消费者正在消费...-1, 当前产品数:0
 生产者正在生产...+1, 当前产品数:1
 消费者正在消费...-1, 当前产品数:0
 生产者正在生产...+1, 当前产品数:1
 消费者正在消费...-1, 当前产品数:0
 生产者正在生产...+1, 当前产品数:1
 消费者正在消费...-1, 当前产品数:0
 生产者正在生产...+1, 当前产品数:1
 生产者正在生产...+1, 当前产品数:2
 消费者正在消费...-1, 当前产品数:1
 生产者正在生产...+1, 当前产品数:2
 消费者正在消费...-1, 当前产品数:1
 生产者正在生产...+1, 当前产品数:2
 消费者正在消费...-1, 当前产品数:1
 生产者正在生产...+1, 当前产品数:2
 生产者正在生产...+1, 当前产品数:3
 消费者正在消费...-1, 当前产品数:2
 生产者正在生产...+1, 当前产品数:3
 消费者正在消费...-1, 当前产品数:2
 生产者正在生产...+1, 当前产品数:3
 消费者正在消费...-1, 当前产品数:2
 生产者正在生产...+1, 当前产品数:3
 消费者正在消费...-1, 当前产品数:2
 生产者正在生产...+1, 当前产品数:3
 生产者正在生产...+1, 当前产品数:4
 消费者正在消费...-1, 当前产品数:3
 生产者正在生产...+1, 当前产品数:4
 消费者正在消费...-1, 当前产品数:3
 生产者正在生产...+1, 当前产品数:4
 消费者正在消费...-1, 当前产品数:3
 生产者正在生产...+1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
箱子已经饱和,生产者停止生产,正在等待消费...
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
箱子已经饱和,生产者停止生产,正在等待消费...
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
箱子已经饱和,生产者停止生产,正在等待消费...
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
箱子已经饱和,生产者停止生产,正在等待消费...
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
箱子已经饱和,生产者停止生产,正在等待消费...
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5
 消费者正在消费...-1, 当前产品数:4
 生产者正在生产...+1, 当前产品数:5


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。