wait和notify方法详解及wai和sleep的区别

wait方法有三个重载方法
public final void wait() throws InterruptedException
public final void wait() throws InterruptedException
public final void wait(long timeout,int nanos) throws InterruptedException

1.wait方法的这三个重载方法都将调用wait(long timeout)这个方法,wait()方法等价于wait(0),0代表永不超时
2.Object的wait(long timeout)方法会导致当前线程进入阻塞,直到有其它线程调用了Object的notify或者notifyAll方法才能将其唤醒,或者阻塞时间达到了timeout时间而自动唤醒。
3.wait方法必须拥有该对象的monitor,也就是wait方法必须在同步方法中使用。
4.当前线程执行了该对象的wait方法之后,将会放弃对该monitor的所有权且进入与该对象关联的wait set中,也就是说一旦线程执行了某个object的wait方法之后,他就会释放对该对象monitor的所有权,其它线程也会有机会继续争抢该monitor的所有权。

notify方法的作用
public final native void notify();
1.唤醒单个正在执行该对象wait方法的线程
2.如果有某个线程由于执行该对象的wait方法而进入阻塞则会被唤醒,如果没有则会忽略
3.被唤醒的线程需要重新获取对该对象所关联monitor的lock才能继续执行

关于wait和notify的注意事项
1.wait方法是可中断方法,这也就意味着,当前线程一旦调用了wait方法进入阻塞状态,其它线程是可以使用interrupt方法将其打断的,可中断方法被打断后会收到中断异常InterruptedException,同时interrupt标识也会被擦除。
2.线程执行了某个对象的wait方法以后,会加入与之对应的wait set中,每一个对象的monitor都有一个与之关联的wait set。
3.当线程进入wait set之后,notify方法可以将其唤醒,也就是从wait set中弹出,同时中断wait中的线程也会将其唤醒。
4.必须在同步方法中使用wait和notify方法,因为执行wait和notify的前提条件是必须持有同步方法的monitor的所有权。

运行下面任何一个方法都会抛出非法的monitor状态异常IllegalMonitorStateException:

public class TestWaitNotify {
    private void testWait(){
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void testNotify(){
        this.notify();
    }

    public static void main(String[] args) {
        TestWaitNotify testWaitNotify = new TestWaitNotify();
//        testWaitNotify.testNotify();
        testWaitNotify.testWait();
    }
}

同步代码的monitor必须与执行wait notify方法的对象一致,简单地说就是用哪个对象的monitor进行同步,就只能用哪个对象进行wait和notify操作。运行下面代码中的任何一个方法,同样都会抛出IllegalMonitorStateException异常:

public class TestWaitNotify1 {

    private final Object MUTEX = new Object();
    private synchronized void testWait(){
        try {
            MUTEX.wait();
//            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    private synchronized void testNotify(){
        MUTEX.notify();
    }

    public static void main(String[] args) {
        TestWaitNotify1 testWaitNotify1 = new TestWaitNotify1();
        testWaitNotify1.testWait();
        testWaitNotify1.notify();
    }

}

上述同步方法中monitor引用的是this,而wait和notify方法使用的却是MUTEX的方法,其实这并不难理解,虽然是在同步方法中执行wait和notify方法,但是wait和notify方法的执行并未以获取MUTEX的monitor为前提。

wait和sleep
从表面上看,wait和sleep方法都可以使当前线程进入阻塞状态,但是两者之间存在着本质的区别,下面我将总结两者的区别和相似之处。
1.wai和sleep方法都可以使线程进入阻塞状态。
2.wait和sleep方法均是可中断方法,被中断后都会收到中断异常。
3.wait是Object的方法,而sleep是Thread特有的方法。
4.wait方法的执行必须在同步方法中进行,而sleep则不需要
5.线程在同步方法中执行sleep方法时,并不会释放monitor的锁,而wait方法则会释放monitor的锁。
6.sleep方法短暂停休眠之后会主动退出阻塞,而wait方法(没有指定wait时间)则需要被其它线程中断后才能退出阻塞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值