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

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

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


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





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值