wait和notify

我们知道线程最核心的一点就是抢占式执行,调度的过程是随机,有时候我们希望可以调配线程的执行顺序。为此wait和notify应运而生。举个例子:wait和notify就类似队友A传球给B,B完成扣篮;B要扣篮就要先wait,等到球传过来;A传球过去,就相当于notify.
以一个线程wait等待,一个线程notify为例

public class Test1 {
	public static void main(String[] args) throws InterruptedException {
		Object object = new Object();
		//线程1进行wait操作
		Thread t1 = new Thread() {
			@Override
			public void run() {
				System.out.println("wait之前");
				try {
					object.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("wait之后");
			}
		};
		//线程2进行notify操作
		Thread t2 = new Thread() {
			@Override
			public void run() {
				object.notify();
			}
		};
		t1.start();
		t2.start();
	}
}

我们预期会打印“wait之前”和"wait之后",但是却编译报错
image.png
原来在wait操作的时候,内部做了三件事

  1. 释放当前锁
  2. 进行等待通知
  3. 满足一定条件的时候(notify),被唤醒,然后重新尝试获取锁

既然要先释放当前锁,那前提肯定是加锁啦。
问:为什么要先释放锁,才进行等待通知?
答:举个例子,A要去ATM取钱,此时A就相当于对ATM进行加锁操作,此时ATM没钱,A就需要离开ATM(释放锁)让工作人员放钱进去(让其他线程加锁),然后工作人员说可以去取钱了(notify唤醒wait),A在重新去取钱(重新获取锁)。

public class Test1 {
	public static void main(String[] args) throws InterruptedException {
		Object object = new Object();
		//线程1进行wait操作
		Thread t1 = new Thread() {
			@Override
			public void run() {
				synchronized (object) {//wati之前先加锁
					System.out.println("wait之前");
					try {
						object.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("wait之后");
				}
			}
		};
		t1.start();
		//由于线程的抢占式执行,为了防止线程t2先执行,调用notify方法,而线程t1还没进入wait
		//导致后续线程t1一直处于wait,线程阻塞状态
		Thread.sleep(500);
		//线程2进行notify操作
		Thread t2 = new Thread() {
			@Override
			public void run() {
				synchronized (object) {//保证加锁对象和调用wait对象是同一个对象
					System.out.println("notify之前");
					object.notify();//同时也要保证调用wait的对象和调用notify对象也是同一个对象
					System.out.println("notify之后");
				}
			}
		};
		t2.start();
	}
}

注意点:

  1. 要保证wait和notify加锁对象相同
  2. 要保证调用wait和notify的对象,是同一个对象

上述代码的流程图
image.png
除了notify,还有notifyAll,多个线程都在wait时,notify是随机唤醒一个线程,而notifyAll则是全部唤醒,这些线程要全部重新竞争锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指挥部在下面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值