Java线程之wait(),notifyAll(),notify()

1.概述

对于多线程来说,生产者—消费者模型是不可避免的问题。“宏观”来说生产者—消费者就是一边生产,一边消费,生产和消费同步。实际上是并发执行,一个线程执行一段时间。生产者生产完成后放入存储缓冲区,消费者从缓冲区拿走产品。那么问题来了:

  1. 同时去竞争缓冲区资源数据怎么保持一致?
  2. 消费者如何知道缓冲区有没有资源?
  3. 生产者如何知道缓冲区资源有没有满?

对于问题1,Java的synchronized关键字可以实现线程同步问题。
对于问题2、3就需要使用wait()、notify(),等待与唤醒。

2.wait()、notify()作用

wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,当前线程被唤醒(进入“就绪状态”)。
注意:wait()、notify()、notifyAll()方法只能在synchronized语句块中使用,这三个方法都是Object的方法,调用的对象是锁对象。 例如:

synchronized(obj){
	obj.wait();

}

wait()方法会释放锁,sleep()方法不释放锁。

3.例子

有一个仓库类entrepot,用list来表示缓冲区(list的长度为1)

class entrepot{
	public List<Integer> res;
	
	public entrepot() {
		// TODO Auto-generated constructor stub
		res=new ArrayList<>();
	}
}

一个生产者线程,负责向list增加数据

class producer extends Thread{
	public entrepot entrepot;
	
	public producer(entrepot entrepot) {
		// TODO Auto-generated constructor stub
		this.entrepot=entrepot;
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized (entrepot) {
			while(true) {
				if(entrepot.res.size()>0) {
					try {
						entrepot.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				try {
					sleep(2000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				int a=(int)(Math.random()*100);
				entrepot.res.add(a);
				System.out.println("生产:"+a);
				entrepot.notifyAll();
			}
		}
		
	}
}

一个消费者线程,负责删除list的数据

class consume extends Thread{
	public entrepot entrepot;
	
	public consume(entrepot entrepot) {
		// TODO Auto-generated constructor stub
		this.entrepot=entrepot;
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized (entrepot) {
			while(true) {
				if (entrepot.res.size()<1) {
					try {
						
						entrepot.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				try {
					sleep(200);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("消费:"+entrepot.res.remove(0));
				entrepot.notifyAll();
			}
		}
		
	}
}

当list的长度为1时,生产者等待,并释放仓库资源,当list长度为0时,消费者等待,并释放仓库资源。生产者生成完成之后就唤醒通知所有的进程,消费者完成后唤醒所有进程。

public class thread3 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		entrepot entrepot=new entrepot();
		producer producer=new producer(entrepot);
		consume consume=new consume(entrepot);
		producer.start();
		consume.start();
	}	

}

运行结果:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值