并发编程-线程间的协作(三)

三、等待与通知

wait()/notify()/notifyAll() 这三个方法都是object 类提供的 其中

wait():

调用该方法的线程进入WAITING 状态,同时释放所持有的对象锁,只有等待通知或者中断才会唤起。

notify():

随机通知一个等待在该对象的线程,使其从wait 方法上唤起,唤起的前提是该线程获取了该对象上的锁,如果没有获取到锁则重新进入WAITING状态

notifyAll():

通知所有等待在该对象上的线程。

其实我们在使用等待与通知是有标准模板的,基本遵循几个原则

注:这边是从某个博客看到,时间久远做了笔记忘记是谁原创的,原作者看到麻烦通知下。。。

等待方:

  1. 获取对象的锁;
  2. 循环里判断条件是否满足,不满足调用wait方法,被通知后仍要检查条件
  3. 条件满足执行业务逻辑

synchronized(对象){

        while(条件不满足){

        对象.wait();

        }

 业务代码

}

通知方:

  1. 获取对象的锁;
  2. 改变条件
  3. 通知所有等待在对象的线程

synchronized(对象){

        改变条件;

        对象.notifyAll();

}

在调用 wait()、notify()系列方法之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用 wait()方法、notify()系列方法。

那么notify()和notifyAll() 我们该怎么选择呢?

在实际开发中我们尽可能使用notifyAll() 而不是notify(),原因就是notify()只会唤醒一个线程,而我们无法确保被唤醒的线程我们需要的,从而增加程序的不确定性。

下面我们使用基本范式演示代码:


/**
 * 等待与通知演示代码
 * wait()/notify()/notifyAll()
 * 
 * @author ckj
 *
 */
public class WaitAntNotifyThread {

	 private static WaitAntNotifyThread waitAntNotifyThread = new WaitAntNotifyThread(10);
	
	private int distance; // 距离


	public WaitAntNotifyThread(int distance) {
		super();
		this.distance = distance;
	}

	/* 线程等待距离发现变化 */
	public synchronized void waitSnack() throws InterruptedException {
		String threadName =Thread.currentThread().getName();
		System.out.println("客户"+threadName+"点了一份快递");
		while (distance > 0) {
			wait();
			System.out.println("改变了距离 thread["
                    +Thread.currentThread().getName()
            +"] 是快递员 notified");
		}
		System.out.println("目前 距离是 "+this.distance);
		
	}

	/* 变化距离 并通知等待线程 */
	public synchronized void notifyShopper() {
		this.distance = 0;
		System.out.println("快递员送餐已到达,通知客户");
		notify();

	}

	/* 变化距离 并通知等待线程 */
	public synchronized void notifyAllShopper() {
		this.distance = 0;
		System.out.println("快递员送餐已到达,通知客户");
		notifyAll();
	}
	
	static class ChangeWait extends Thread{
		@Override
		public void run() {
			
			try {
				waitAntNotifyThread.waitSnack();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	
	
	public static void main(String[] args) throws InterruptedException {
		// 唤起三个线程
		for(int i=0;i<3;i++) {
			new ChangeWait().start();
		}
		 Thread.sleep(1000);
		 waitAntNotifyThread.notifyShopper(); // 随机唤起
		 //waitAntNotifyThread.notifyAllShopper(); // 全部唤起
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值