多线程--生产者消费者问题(wait和notify方法)

java.lang.Object类中提供了wait(),notify(),notifyAll()方法,这些方法只有synchronized方法或者synchronized代码块中才能使用。

当synchronized方法或者synchronized代码块中的wait方法被调用时,当前线程呗中断运行,并且放弃该对象的锁。当另外的线程执行了某个对象的notify方法会唤醒在此对象等待池中的某个线程,使之成为可运行的线程。notifyAll方法会唤醒所有等待这个对象的线程,使之成为可运行的线程。


经典的生产者、消费者问题:

问题描述:生产者将产品交给店员,而消费者从店员处取走产品,店员一次只能持有固定数量的产品,如果生产者生产了过多的产品,店员会叫生产者等一下,如果店内有空位放产品了,则通知生产者继续生产;如果店内没有产品了,店员会告诉消费者等一下,如果店中有产品了,在通知消费者来取走产品。


解决方案:

package com.tan;
//产品类:为产品提供一个含有表示的id属性
class Products{
	int id;
	public Products(int id) {
		this.id=id;
	}
	//要在生成或者消费时打印产品的详细内容,需重写toString()方法
	@Override
	public String toString() {
	
		return "Products"+id;
	}
}

//店员类:店员一次只能持有10份产品,
//注意:只有锁定对象后才可以用wait方法,否则会出错。 notify和wait是一一对应的。
class Clerk{
	//默认0个产品
	int index =0;
	Products [] pro=new Products[10];
	//生产者生产出来的产品交给店员
	public synchronized void addProuct(Products pd){
		while(index==pro.length){
			try {
				this.wait();//产品已满,请稍后在生产
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notify();//通知等待区的消费者可以取走产品了
		pro[index]=pd;
		index++;
	}
	
	//消费者从店员处取产品
	public synchronized Products getProduct(){
		while(index==0){
			try {
				this.wait();//缺货,请稍后再取
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notify();//通知等待区的生产者可以生产产品了
		index--;
		return pro[index];
	}	
}

//生产者线程类:生产者与店员有关系,店员类被当做属性引入 进来
class Producer implements Runnable{
	private Clerk clerk;
	public Producer(Clerk clerk) {
		this.clerk=clerk;
	}
	@Override
	public void run() {
	System.out.println("生产者开始生产产品");
	for(int i=0;i<15;i++){//注意这里的循环次数一定要大于pro数组的长度
		Products pd=new Products(i);
		clerk.addProuct(pd); //生产产品
		System.out.println("生产了:"+pd);
		try {
			//将睡眠时间设置为随机产生的值
			Thread.sleep((int)(Math.random()*10)*100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
			
	}
		
	}
}


//消费者线程类:消费者与店员也有关系,所以也本地当做属性被引入进来,同样通过构造器完成初始化店员类对象的任务
class Consumer implements Runnable{
	private Clerk clerk;
	public Consumer(Clerk clerk) {
		this.clerk=clerk;
	}
	@Override
	public void run() {
		System.out.println("消费者开始取走产品");
		for(int i=0;i<15;i++){
			Products pd=clerk.getProduct();
			System.out.println("消费了:"+pd);
			try {
				Thread.sleep((int)(Math.random()*10)*100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
}


//测试类
public class ProductTest {
	public static void main(String[] args) {
		Clerk clerk=new Clerk();
		Thread producerThread=new Thread(new Producer(clerk));
		Thread consumerThread=new Thread(new Consumer(clerk));
		producerThread.start();
		consumerThread.start();
		
	}
}


输出结果:

生产者开始生产产品
消费者开始取走产品
生产了:Products0
消费了:Products0
生产了:Products1
消费了:Products1
生产了:Products2
消费了:Products2
生产了:Products3
消费了:Products3
消费了:Products4
生产了:Products4
消费了:Products5
生产了:Products5
生产了:Products6
生产了:Products7
生产了:Products8
消费了:Products8
生产了:Products9
生产了:Products10
消费了:Products10
生产了:Products11
消费了:Products11
生产了:Products12
生产了:Products13
消费了:Products13
消费了:Products12
生产了:Products14
消费了:Products14
消费了:Products9
消费了:Products7
消费了:Products6

你可能感兴趣的:(多线程--生产者消费者问题(wait和notify方法))