一:从一道面试题说起
启动两个线程, 一个输出 1,3,5,7…99, 另一个输出 2,4,6,8…100 最后 STDOUT 中按序输出
1,2,3,4,5…100
要求用 Java 的 wait + notify 机制来实现
解法:
public class Test {private static Object lock = new Object();private static volatile int index = 0;public static void main(String[] args) {Runnable task = new Runnable() {public void run() {for(int i=0; i<50; i++) {synchronized (lock) {index++;System.out.println(index);try {if(index %2 ==0) {lock.notify();}else {lock.wait();}} catch (InterruptedException e) {e.printStackTrace();}}}}};new Thread(task).start();new Thread(task).start();}
}
二:wait and notify
首先看下wait方法的Java Doc介绍:
Causes the current thread to wait until either another thread invokes
the
* {@link java.lang.Object#notify()} method or the
* {@link java.lang.Object#notifyAll()} method for this object, or a
* specified amount of time has elapsed.
*
* The current thread must own this object’s monitor.
*
翻译一下就是:
导致当前线程阻塞,一直等到别的线程调用了notify()或notifyAll()方法
当前线程必须持有这个 对象的锁(monitor)
方法签名:
public final native void wait(long timeout) throws InterruptedException;
然后看下notify()的Java Doc介绍:
/**
* 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.
翻译一下大概就是:
唤醒任意一个正在等待当前对象的monitor锁的线程。 若有多个线程处于此 object 控制权下的 wait 状态,只有一个会被唤醒。
方法签名:
public final native void notify();
再看下notifyAll()的Java Doc介绍:
/**
* 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.
翻译一下大概就是:
唤醒所有正在等待当前对象的monitor锁的线程。
方法签名:
public final native void notifyAll();
三:总结
wait 和 notify 均为 Object 的实例方法:
- Object.wait()——暂停一个线程
- Object.notify()——唤醒一个线程
- Object.notifyAll()——唤醒所有等待Object对象锁的线程
另外:
- 都需要拥有Object对象锁才能调用
- 可以使用此机制进行多线程之间的协同、通信,实现多线程的可见性