Java并发编程之Object.wait()/notify()

场景:

        1 双筷子,1 个或者多个人,餐桌每次只能一个人上去吃饭,其他人等待餐桌上的人吃完才有机会上去吃 。餐桌上吃完的那个人必须通知在等待吃饭的人说自己吃完了,你们可以吃了,此时在等待的人收到这个信号后,通过争抢的方式看谁先抢到筷子谁就能上餐桌吃饭,其他人继续等待 ;

        在并发机制中,相当于线程的并发问题,该问题的关键在于怎么实现 等待与通知 的调度机制 ?
 

怎么办:

最简单的方式就是让等待者不断地循环检查变量是否符合预期,如下面代码所示,在while循环中设置不满足的条件,如果条件满足就退出循环,从而完成等待者的工作。

while (<判断条件==true>) {
    try {
        Thread.sleep(2000);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
 
doSomething();

该段代码在不满足条件时就睡眠一段时间,其目的是减少过多的无效尝试,降低对处理器资源的浪费,上述方式存在以下问题:

1、难以确保及时性,在睡眠时,基本不消耗处理器资源,但是如果睡眠过久,就不能及时发现条件的变化,也就是及时性难以保证。

2、难以降低开销,如果睡眠时间降低为1毫秒,这样当前线程就能很迅速地发现条件的变化,但是却可能消耗更多的处理器资源,造成了无端的浪费。

以上两个问题,看似矛盾难以调和,但是通过Java的wait()/notify()实现的等待/通知机制就能够很好地解决这个矛盾并实现所需的功能。

等待/通知的相关方法是任意Java对象都具备的!!!因为这些方法被定义在所有对象的超类java.lang.Object上,Object作为java中所有对象的基类,其存在的价值不言而喻,其中wait()和notify()方法的实现为多线程协作提供了保证。

 

等待/通知的相关方法描述如下:

也可以看官方的JDK-API文档:https://docs.oracle.com/javase/8/docs/api/index.html

方法名称描述
notify()通知一个在对象上等待的线程,使其从wait()返回,而返回的前提是该线程获取到了对象的锁。
notifyAll()通知所有等待在该对象上的线程。
wait()通调用该方法的线程进入WAITING状态,只有等待另外线程的通知或被中断才会返回,需要注意,调用wait()方法后,会释放对象的锁
wait(long)超时等待一段时间,这里的参数是毫秒,也就是等待长达n毫秒,如果没有通知就超时返回。
wait(long, int)对于超时时间更细粒度的控制,可以达到毫秒。

关于wait() / notify()机制先看下网上的一个demo:

public class WaitNotifyTest {
	public static void main(String[] args) {
		Object lock = new Object();
		
		new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程A等待获取lock锁");
                synchronized (lock) {
                    try {
                        System.out.println("线程A获取了lock锁");
                        Thread.sleep(1000);
                        System.out.println("线程A将要运行lock.wait()方法进行等待");
                        lock.wait();
                        System.out.println("线程A等待结束");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
		
		new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程B等待获取lock锁");
                synchronized (lock) {
                    System.out.println("线程B获取了lock锁");
                    try {
                    	Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程B将要运行lock.notify()方法进行通知");
                    lock.notify();
                }
            }
        }).start();
	}
}

运行结果:
线程A等待获取lock锁
线程A获取了lock锁
线程B等待获取lock锁
线程A将要运行lock.wait()方法进行等待
线程B获取了lock锁
线程B将要运行lock.notify()方法进行通知
线程A等待结束

可以看到通过wait()/notify()完美实现了等待/通知机制 。
 

方法解析:

偷一下懒,贴个官方的wait() / notify() 方法详解上来,嘿嘿~

wait():

https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait-long-
wait()

 

notify():

https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#notify–
notify()
 

Mark:

  • wait() / notify() 机制是多线程之间通信的一种方式 ;
  • 线程之间获取锁没有先后顺序,而是通过随机、抢占的方式,可能导致线程饥饿 ;

 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值