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
时间: 2024-10-13 13:25:19

Java 多线程实现生产者消费者问题(wait/notify)的相关文章

java多线程解决生产者消费者问题

import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class Test { public static void main(String[] args) { GunClip clip = new GunClip(); Producer p = new Producer(clip); customer c = new customer(clip); p.star

JAVA多线程之生产者消费者

生产者消费者并发编程: 假设仓库有10个仓位,分别有10个生产者和10个消费者,生产者不断生产产品,放入仓库的仓位中,而消费者则不断从仓库中获取产品, 如果仓库已满,则生产者要等待,等消费者消费后,空出仓位后,再继续放入产品. 反之如果仓库已空,则消费者要等待,等待生产者生产出产品后,再继续消费产品. 关于生产者.消费者有四种实现方式 1,wait,nofity方式 2,ReentrantLock锁的await()和signal() 3,阻塞队列的方式 4,Semaphore 信号量方式 下面分

java多线程模拟生产者消费者问题,公司面试常常问的题。。。

package com.cn.test3; //java多线程模拟生产者消费者问题 //ProducerConsumer是主类,Producer生产者,Consumer消费者,Product产品 //Storage仓库 //批注:我把输出结果写在程序以下了,你能够看一下,事实上非常easy的,你想象一下产品从生产,到取出的一个生产线,我们定义两个线程,生产者线程,和消费者线程,一个是生产者不停的生产产品并放入数量有限的指定槽内,而消费者从指定槽依次取出产品,现实中的流水车间也相似于此. publ

java多线程--“升级版”生产者消费者

ReentrantLock介绍 ReentrantLock是一个可重入的互斥锁,又被称为"独占锁". 顾名思义,ReentrantLock锁在同一个时间点只能被一个线程锁持有:而可重入的意思是,ReentrantLock锁,可以被单个线程多次获取. ReentrantLock分为"公平锁"和"非公平锁".它们的区别体现在获取锁的机制上是否公平."锁"是为了保护竞争资源,防止多个线程同时操作线程而出错,ReentrantLock

Java多线程:生产者消费者更佳的解决方法(确定不会出现死锁)

今天看了一片博文,讲Java多线程之线程的协作,其中作者用程序实例说明了生产者和消费者问题,但我及其他读者发现程序多跑几次还是会出现死锁,百度搜了下大都数的例子也都存在bug,经过仔细研究发现其中的问题,并解决了,感觉有意义贴出来分享下. 下面首先贴出的是有bug的代码,一个4个类,Plate.java: package CreatorAndConsumer; import java.util.ArrayList; import java.util.List; /** * 盘子,表示共享的资源

Java多线程之生产者消费者问题&amp;lt;一&amp;gt;:使用synchronized keyword解决生产者消费者问题

今天看了一片博文,讲Java多线程之线程的协作,当中作者用程序实例说明了生产者和消费者问题,但我及其它读者发现程序多跑几次还是会出现死锁,百度搜了下大都数的样例也都存在bug,经过细致研究发现当中的问题.并攻克了,感觉有意义贴出来分享下. 以下首先贴出的是有bug的代码,一个4个类.Plate.java: package CreatorAndConsumer; import java.util.ArrayList; import java.util.List; /** * 盘子,表示共享的资源

[Java] 多线程下生产者消费者问题的五种同步方法实现

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题. 生产者消费者模式的优点 - 解耦 - 支持并发 - 支持忙闲不均 解决方法可分为两类: (1)用信号量和锁机制实现生产者和消费者之间的同步: - wait() / notify()方法 - await() / signal()方法 - BlockingQueue阻塞队列方法 - Semaphore方法 (2)在生产者和消费者之间建立一个管道.(一般不使用,缓冲区不易控制.数据不易封装和传输) - PipedInputStream

Java多线程实现生产者消费者延伸问题

在操作系统中有一类问题被称为生产者消费者问题:意为,有数个生产者生产产品,有数个消费者消费产品,他们共享一定数量的缓存. 这里用java多线程编程,实现生产者消费者问题的一种延伸,橘子苹果问题. 题目如下: 有苹果橘子生产者各20个,有苹果橘子消费者各20个,他们公用20个缓存区.要求能随时查看缓存区内容,随时查看生产消费内容情况,随时暂停生产开始生产. 我们的实现思路: 1.首先创建一个缓存区类,其中包含静态的,长度大小为20的数组,用来存放和取出生产的产品:一个静态的日志变量List,用来记

JAVA多线程之生产者消费者模式

一.什么是生产者消费者模式? 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力. 二.为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产

Java多线程同步——生产者消费者问题

这是马士兵老师的Java视频教程里的一个生产者消费者问题的模型 [java] view plaincopy public class ProduceConsumer{ public static void main(String[] args){ SyncStack ss = new SyncStack(); Producer pro = new Producer(ss); Consumer con = new Consumer(ss); new Thread(pro).start(); new