Demo 代码:
public class WaitNotifyDemo {
private static boolean flag = true;
private static final Object lock = new Object();
public static void main(String[] args) throws Exception {
Thread waitThread = new Thread(new Wait(), "Wait Thread");
waitThread.start();
Thread.sleep(1000);
Thread notifyThread = new Thread(new Notify(), "Notify Thread");
notifyThread.start();
}
private static class Wait implements Runnable {
@Override
public void run() {
synchronized (lock) {
while (flag) {
try {
System.out.println(Thread.currentThread() + " flag is true. wait @ " +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.wait(); // wait thread 由于 Object.wait() 被阻塞,并释放 monitor
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
System.out.println(Thread.currentThread() + " flag is false. running @ " +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
}
private static class Notify implements Runnable {
@Override
public void run() {
synchronized (lock) {
System.out.println(Thread.currentThread() + " hold lock. notify @ " +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
// lock.notifyAll();
lock.notify();
flag = false;
try {
Thread.sleep(5000); // Thread.sleep() 不会释放锁
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
synchronized (lock) {
System.out.println(Thread.currentThread() + " hold lock again. sleep @ " +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
}
}
输出信息:
Thread[Wait Thread,5,main] flag is true. wait @ 14:51:52
Thread[Notify Thread,5,main] hold lock. notify @ 14:51:53
Thread[Notify Thread,5,main] hold lock again. sleep @ 14:51:58
Thread[Wait Thread,5,main] flag is false. running @ 14:52:03
Process finished with exit code 0
由以上 Demo 可以知道
- Object.wait() 方法会阻塞线程,并释放锁
- Thread.sleep() 方法会阻塞线程,但不会释放锁,被阻塞的线程将继续持有锁
- Object.notify()、Object.notifyAll() 方法会唤醒被阻塞的线程,notify 随机唤醒一个,notifyAll 唤醒所有
尝试一下 Object.wait(timeout) 和 Thread.join() 方法
public class WaitNotifyDemo {
private static boolean flag = true;
private static final Object lock = new Object();
public static void main(String[] args) throws Exception {
Thread waitThread = new Thread(new Wait(), "Wait Thread");
waitThread.start();
Thread.sleep(1000);
Thread notifyThread = new Thread(new Notify(), "Notify Thread");
notifyThread.start();
waitThread.join();
System.out.println("join test");
}
private static class Wait implements Runnable {
@Override
public void run() {
synchronized (lock) {
while (flag) {
try {
System.out.println(Thread.currentThread() + " flag is true. wait @ " +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.wait(300); // wait thread 由于 Object.wait() 被阻塞,并释放 monitor
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
System.out.println(Thread.currentThread() + " flag is false. running @ " +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
}
private static class Notify implements Runnable {
@Override
public void run() {
synchronized (lock) {
System.out.println(Thread.currentThread() + " hold lock. notify @ " +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
// lock.notifyAll();
lock.notify();
flag = false;
try {
Thread.sleep(5000); // Thread.sleep() 不会释放锁
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
synchronized (lock) {
System.out.println(Thread.currentThread() + " hold lock again. sleep @ " +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
}
}
输出:
Thread[Wait Thread,5,main] flag is true. wait @ 15:04:54
Thread[Wait Thread,5,main] flag is true. wait @ 15:04:55
Thread[Wait Thread,5,main] flag is true. wait @ 15:04:55
Thread[Wait Thread,5,main] flag is true. wait @ 15:04:55
Thread[Notify Thread,5,main] hold lock. notify @ 15:04:55
Thread[Notify Thread,5,main] hold lock again. sleep @ 15:05:00
Thread[Wait Thread,5,main] flag is false. running @ 15:05:05
join test
JDK 源码中关于 Thread.join() 的注释如下:
/**
* Waits for this thread to die.
*
* <p> An invocation of this method behaves in exactly the same
* way as the invocation
*
* <blockquote>
* {@linkplain #join(long) join}{@code (0)}
* </blockquote>
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
在 Demo 的代码中,在 main 方法(主线程) 中调用 waitThread.join() 将会导致 主线程阻塞,等待 waitThread 结束后,继续执行
参考资料:
1、《Java 并发编程艺术》
2、JDK 源码