生产者和消费者问题【等待通知机制实现】

1.生产者和消费者问题是经典的问题,这里利用等待通知机制实现:wait(),notify()

重复下多线程问题的一般框架:



多线程的程序一般框架 :


1.一个服务类A,用于生成对象a,a中包含多个的同步方法或者同步块;a.method1(); a.mothod2();


2.多个线程类:线程类ThreadA,线程类ThreadB;含有一个A类型的私有变量,构造函数中对其赋值;


Run中调用a中的同步方法;


3.主程序:将类A的对象a通过构造函数给ThreadA/ThreadB的A类型的成员,启动线程。



首先实现

一个生产者和一个消费者

操作值的方式实现(操作栈也可以实现):

第一个java类是:ValueObject 工具类,里面包含一个公开的静态变量,供消费者和生产者共享;


public class ValueObject {
	public static String value="";
}



第二个是一个

生产者类:包括同步块生产过程。


package com.mytest.pc;

//生产者
public class Production {
	private String lock;
	public Production(String lock){
		super();
		this.lock=lock;
	}
	public void setValue(){
		synchronized (lock) {
			if(!ValueObject.value.equals("")){//不为空值;则等待后生产;
				try {
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			//空,则可以生产;
			String valueString=System.currentTimeMillis()+"_"
			+System.nanoTime();
			System.out.println("set的值为:"+valueString);
			ValueObject.value=valueString;
			lock.notify();
		}
		
	}
}



下面是

消费者的java类:包括同步消费块;


package com.mytest.pc;

//生产者
public class Consumer {
	private String lock;
	public Consumer(String lock){
		super();
		this.lock=lock;
	}
	public void getValue(){
		synchronized (lock) {
			if(ValueObject.value.equals("")){//为空值;则等待后消费;
				try {
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			//不空,则可以消费;
			System.out.println("get值为:"+ValueObject.value);
			ValueObject.value="";
			lock.notify();
		}
		
	}
}

下面是

生产者的线程类Java类:生产方法


package com.mytest.pc;

public class ThreadP extends Thread {
	private Production p;
	
	public ThreadP(Production p){
		super();
		this.p=p;
	}
	
	@Override
	public void run() {
		while(true){
			p.setValue();
		}
	}

}



下面是消费者的线程类Java类:消费方法;



package com.mytest.pc;

public class ThreadC extends Thread {
	private Consumer c;
	
	public ThreadC(Consumer c){
		super();
		this.c=c;
	}
	
	@Override
	public void run() {
		while(true){
			c.getValue();
		}
	}

}


下面是主程序测试类


package com.mytest.pc;

public class P1_C1_test {
	public static void main(String[] args) {
		String lock="";
		Production production=new Production(lock);
		Consumer consumer=new Consumer(lock);
		
		ThreadP p=new ThreadP(production);
		ThreadC c=new ThreadC(consumer);
		p.start();
		c.start();
		//ThreadP p2=new ThreadP(production);
		//ThreadC c2=new ThreadC(consumer);
		//p2.start();
		//c2.start();

	}

}



程序测试结果如下:程序运行正确,不停的生产和消费,而且生产和消费的值一致。

set的值为:1491730702480_2881014140368
 get值为:1491730702480_2881014140368
 set的值为:1491730702480_2881014157414
 get值为:1491730702480_2881014157414
 set的值为:1491730702480_2881014173910
 get值为:1491730702480_2881014173910

改写为多个生产者+1个消费者;n-1;

           1个生产者+多个消费者;1-n;

           多个生产者+多个消费者。n-n;

测试办法:

1.将测试主函数中添加如下代码;

ThreadP p2=new ThreadP(production);
ThreadC c2=new ThreadC(consumer);
p2.start();
c2.start();

              2.把类生产者Production和消费者类Consumer中的if改为while.

             3. 运行效果: 程序会结束,但中途停止打印输出。

程序都会出现假死状态

假死,就是线程进入了waiting状态。

原因:生产者唤醒的可能是生产者,消费者唤醒的可能是消费者。不能保证notify()唤醒的是异类。

解决办法:将notify()改为notifyAll();


多线程中经常遇到的两个问题:

1.通过过早问题:通过发生了,wait不必再执行,而已在通知后设置个flag,根据flag判断有无必要再执行wait;

2.等待wait的条件发生了变化:if判断改为while();


备注:可以通过操作栈实现生产者和消费者问题。