logo头像

勤求古训,博采众方

wait与notify的解析

本文于 767 天之前发表,文中内容可能已经过时。

wait和notify都是object的方法,加上重载总共5个方法,而object总共才12个方法,可见这两个方法的重要性

介绍

  • wait和notify都是object的方法,加上重载总共5个方法,而object总共才12个方法,可见这两个方法的重要性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public final native void notify();

public final native void notifyAll();

public final void wait() throws InterruptedException {
wait(0);
}

public final native void wait(long timeout) throws InterruptedException;

public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}

if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}

if (nanos > 0) {
timeout++;
}

wait(timeout);
}
  • 用实际例子来说明下,synchronized是来做同步锁,那具体是什么作用呢?其实就是监视器,比如下面的代码中lock对象先通过synchronized关键字来监视线程A的代码块,然后线程A拿到锁,睡1秒,然后调用了lock.wait,这里的话讲下wait的作用他会释放监视器lock对象,那么其他线程就可以使用这个监视器了。

  • 接下来,线程B被lock对象监视了,然后睡5秒,下面马上调用了lock.notify方法,这个notify的作用是什么呢?它会通知lock对象监视的第一个等待的线程,jdk的注释讲的是随机通知,但是jvm当中是取第一个,这里要看jvm的实现,然后这个时候线程B的代码块还没执行完,下面还有个字符串输出,等到这个执行完之后,线程A就可以执行下面的代码了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.example.common.utils;

import java.util.concurrent.TimeUnit;

public class WaitNotify {

final static Object lock = new Object();

public static void main(String[] args) {

new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程 A 等待拿锁");
synchronized (lock) {
try {
System.out.println("线程 A 拿到锁了");
TimeUnit.SECONDS.sleep(1);
System.out.println("线程 A 开始等待并放弃锁");
lock.wait();
System.out.println("A被通知可以继续执行 则 继续运行至结束");
} catch (InterruptedException e) {
}
}
}
}, "线程 A").start();

new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程 B 等待锁");
synchronized (lock) {
System.out.println("线程 B 拿到锁了");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
}
lock.notify();
System.out.println("线程 B 随机通知 Lock 对象的某个线程");
}
}
}, "线程 B").start();
}


}

参考