多线程 notify()和wait()实现生产者-消费者模型

首先了解notify()和wait()的功能是什么?

wait()notify()是每个对象都有的两个方法。考虑在两个线程的问题中,对象obj在这两个线程中都可以引用,在一个线程中,对象obj调用wait()方法导致线程阻塞,该线程在执行到这一行后便停止等待,直到另一线程中该obj对象调用notify()方法后才开始继续运行wait()之后的代码。

notify()的功能是随机激活一个在该对象下阻塞的线程。如果是两个线程中的对象都调用了wait()方法后都阻塞等待,那么另一个线程中的对象调用notify()后,只是随机的通知前面两个阻塞的线程中的一个线程激活,要使所有的阻塞线程都激活可以用notifyAll()方法。

wait()方法要写在try{}语句里。不仅,还要写在synchronized(){}语句里,因为当想要调用wait( )进行线程等待时,必须要取得这个锁对象的控制权,防止其他线程修改状态。

生产者消费者模型的建立

现考虑这样一种情况:有一个栈s,第一个线程只负责往这个栈s里放数据,也就是执行push操作。第二个线程只负责从这个栈s中取数据,也就是执行pop操作。那么现在第一个线程就像一个生产者一样,负责生产数据,而第二个线程就像消费者一样,消耗数据。这就是生产者消费模型,他们都对一块公共的数据进行操作。

那么这种模型就会产生这么几种情况:

  1. 生产者的生产速度和消费者的消费速度一样。
  2. 生产者生产速度大于消费者消费速度。
  3. 生产者生产速度小于消费者消费速度。

第一种情况的话,工作的很协调。

第二种情况随着时间的推移,栈的空间会被存满,那么这个时候生产者就不能再生产数据了,需等到消费者消费了数据之后才能生产数据。如果生产者使用if语句判断栈的空间有无剩余的话,行是能行,只不过这个线程一直在运行if语句,还在占用系统资源,对系统性能有很大影响。有一种比较好的方法就是:当空间满的话,生产者就等待,线程阻塞,释放资源,等待消费者消耗了数据的时候,再激活生产者线程。

反过来,第三种情况当栈s空时,消费者便进入等待,线程阻塞,如果生产者生产了数据后,再激活消费者线程。

最后贴上我的测试代码。

生产者:

import java.util.Stack;

public class Producer extends Thread {
	public  Stack<Integer> s;
	
	public Producer(Stack<Integer> s) {
		this.s = s;
	}
	@Override
	public void run() {
		while(true) {
			
			synchronized(s)
			{
				if(s.size()>30) {
					
					try {
						System.out.println("producer wait");
						s.wait();
						
					}
						catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				s.push(s.size());
				System.out.println("生产者:"+"push:"+s.size());
				s.notify();
			}
		}
	}
}

消费者:



import java.util.Stack;

public class Consumer extends Thread {
	
	public  Stack<Integer> s;
	
	public Consumer(Stack<Integer> s) {
		this.s = s;
	}
	

	@Override
	public void run() {
		while(true)
		{
			synchronized(s)
			{
				if(s.size()==0)
				{			
					try {
						System.out.println("消费者等待");
						s.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}	
				}
				System.out.println("消费:"+(s.pop()+1));
				s.notify();
			}
		}
	}
}

测试类:

import java.util.Stack;

public class Main {
	public static Stack<Integer> s =new Stack<>();

public static void main(String[] args) {
	System.out.println(s.size());
	Producer p = new Producer(s);
	Consumer c = new Consumer(s);
	
	p.start();
	c.start();
}	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值