关于wait和notify的注意事项

众所周知wait和notifyObject中的方法,也就是说在JDK中每一个类都拥有这两个方法,其中wait有三个重载的方法。

Wait

public final void wait() throws InterruptedException;永不超时

public final void wait(long timeout) throws InterruptedException;当前线程进入阻塞,知道其他线程调用notify/notifyAll或者阻塞时间到达了timeout自动唤醒

public final void wait(long timeout,int nanos) throws InterruptedException;

1、wait方法必须拥有该对象的monitor,也就是说wait方法必须在同步方法中使用

2、当线程执行了该对象的waitf方法之后,就会放弃该对象的monitor的所有权并且进入该对象关联的wait Set中,也就是说一旦线程执行了某个对象的wait方法之后,就会放弃该对象的monitor的所有权,其它线程就有机会去争抢该对象的monitor所有权

Notify

public final native void notify();

1、唤醒单个正在执行该对象的wait方法的线程(sleep并不能唤醒)

2、如果某个线程执行了该对象的wait方法二进入阻塞则会被唤醒,没有则忽略

3、被唤醒的线程需要重新获取该对象所关联的monitor的lock才能继续执行

两者注意事项:

1、wait方法是可中断的方法,也就意味着线程一旦调用了wait方法进入阻塞,其它线程是可以使用interrupt方法将其打断的,此时会进入interruptedException异常,同时interrupt标识也会被擦除

2、线程执行了某个对象的wait方法之后,会加入与之对应的wait set中,每一个对象的monitor都有一个与之关联的wait set,线程进入wait set之后notify方法可以将其唤醒,也就是从wait set中弹出,同时中断wait中的线程也会将其唤醒。

3、必须在同步方法中使用wait和notify,因为执行wait和notify的前提条件是必须持有同步方法的monitor的所有权,运行下面任何一个方法都会抛出非法monitor状态异常IllegalMonitorStateException

    //没在同步方法啊中调用wait/notify方法
    private  void test(){
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

4、同步代码块中或同步方法中必须与wait notify方法的对象一致,简单的来说就是对哪个对象的monitor的进行同步,就只能对该对象进行wait或notify操作。

    //案例一:同步方法中调用wait   monotor关联的对象不一致
    public synchronized void  test2(){
            try {
                Thread.currentThread().wait(3000);//this
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }

    //案例二:关联monitor对象与wait和notify对象不一致
    private Object Mut = new Object(); 
    private syncronized void testWait(){
        try{
            Mut.wait();
        }catch(InterruptedException e){
            e.printStackTrance();
        }
    }
    private Syncronized void testNotify(){
        Mut.notify();
    }

顺便说一下面试常问的面试题:wait和sleep的区别?

相同:1、wait和sleep方法都可以使线程进入阻塞状态,并且两者都是可中断的方法,被中断后会收到中断异常

不同:1、wait是Object方法,sleep是Thread特有的方法

           2、wait方法需要在同步方法中执行,而sleep不要

           3、线程在同步方法中执行sleep方法时,并不会释放monitor的锁,而wait会释放

           4、sleep方法短暂休眠之后会主动退出阻塞,而wait方法之后(没指定时间)需要其他线程中断或者唤醒才能退出阻塞

猜你喜欢

转载自blog.csdn.net/qq_40826106/article/details/86306454