java多线程--wait/notify/notifyAll 理解

最近重新看了一下多线程方面的,对于 Object 本身提供的三个方法 wait(),notify(),notifyAll() 都没有好好研究过,大多都是基于书籍跟文档而已,所以重新用代码跑了一遍记录一下,加深下印象。

1、wait()

官方文档是这样描述的:

Causes the current thread to wait until another thread invokes the{@link java.lang.Object#notify()} method or the
{@link java.lang.Object#notifyAll()} method for this object.
In other words, this method behaves exactly as if it simply
performs the call {@code wait(0)}.

简单来说就是只有调用了 notify() 方法或者 notifyAll() 才能唤醒当前调用了 wait() 方法的线程。

也是就是调用了 wait() 方法的线程会进入等待状态。

文档后面还有一段话:

* This method should only be called by a thread that is the owner
* of this object's monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
也就是说只有持有改对象的锁(监视器 monitor)才可以调用 wait() 方法,调用之后会把当前的监视器(锁)交给其他线程。

2、notify() 

文档描述如下:

* Wakes up a single thread that is waiting on this object's
* monitor. If any threads are waiting on this object, one of them
* is chosen to be awakened. The choice is arbitrary and occurs at
* the discretion of the implementation. A thread waits on an object's
* monitor by calling one of the {@code wait} methods.

唤醒任意一个在等到获取监视器(锁 monitor)的线程,并且是随机的,只能唤醒一个。

同样也有跟 wait() 方法类似的一段描述:

* This method should only be called by a thread that is the owner
* of this object's monitor. A thread becomes the owner of the
* object's monitor in one of three ways:

该方法也是必须在持有对象的锁(监视器 monitor)才可以调用。

3、notifyAll()

文档描述:

* Wakes up all threads that are waiting on this object's monitor. A
* thread waits on an object's monitor by calling one of the
* {@code wait} methods.

跟 notify() 的不同就是 notifyAll() 唤醒的是所有 wait 中的线程。但是唤醒的不是立即执行,必须等待当前线程执行完成之后,等待唤醒的线程才会去竞争获取 monitor。

并且 notifyAll() 与 notify() 一样,也是必须在持有对象的 monitor 的时候才可以调用。

4、代码验证

    4.1、多线程单对象调用 wait() 

public class MyTest {

    public synchronized void t1(String name){
        System.out.println(name + ":t1 method");
    }
    public synchronized void t2(String name){
        System.out.println(name + ":t2 method with wait()");
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + ":t2 method with wait() after notify");
    }
    public synchronized void t3(String name){

        System.out.println(name + ":t3 with notify");
        notify();
        System.out.println(name + ":t3 after notify");

    }

    public static void main(String[] args) throws InterruptedException {
        MyTest test = new MyTest();


        new Thread(new Runnable() {
            @Override
            public void run() {
                test.t1("Thread 1");
                test.t2("Thread 1");
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test.t1("Thread 2");
                test.t2("Thread 2");
            }
        }).start();

        
    }

}

输出结果如下并且主线程一直处于等待状态没有结束:

Thread 1:t1 method
Thread 1:t2 method with wait()
Thread 2:t1 method
Thread 2:t2 method with wait()

    4.2、多线程单对象调用 wait(),调用 notify() 

    在4.1 的基础上,main 方法改成如下:

public static void main(String[] args) throws InterruptedException {
        MyTest test = new MyTest();


        new Thread(new Runnable() {
            @Override
            public void run() {
                test.t1("Thread 1");
                test.t2("Thread 1");
                test.t1("Thread 1");
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test.t1("Thread 2");
                test.t2("Thread 2");
            }
        }).start();

        // 确保线程1跟2都已经跑了
        Thread.sleep(1000);
        new Thread(new Runnable() {
            @Override
            public void run() {
                test.t3("Thread 3");

            }
        }).start();
    }

输出结果如下,并且当前主线程处于等待阻塞状态:

Thread 2:t1 method
Thread 2:t2 method with wait()
Thread 1:t1 method
Thread 1:t2 method with wait()
Thread 3:t3 with notify
Thread 3:t3 after notify
Thread 2:t2 method with wait() after notify

很明显当执行了 Thread 3  的时候,处于 wait 状态的 Thread 1 跟 2 都在等待 Thread 3 执行之后加入竞争获取 minor,多执行几遍会发现之后一句话的结果可能是下面两句其中一句,因为只有一个线程会被唤醒。

Thread 2:t2 method with wait() after notify
Thread 1:t2 method with wait() after notify

    4.3、多线程单对象调用 wait(),调用 notifyAll()

    延用4.2的main方法,但是需要改下 t3()  的 notify 为 notifyAll

    输出结果如下:

Thread 1:t1 method
Thread 1:t2 method with wait()
Thread 2:t1 method
Thread 2:t2 method with wait()
Thread 3:t3 with notify
Thread 3:t3 after notify
Thread 2:t2 method with wait() after notify
Thread 1:t2 method with wait() after notify

    很明显,Thread 1跟2 都被唤醒了并且执行完。


总结:

    wait 与 notify/notifyAll 都是搭配使用,并且是对于同一对象同一个锁的情况下,执行 wait 的对象释放的锁需要等到其他线程调用 notify/notifyAll 并且执行完当前线程才有机会被唤醒继续执行下去。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值