Object对象的wait()方法和notify()方法通常用于线程之间的阻塞和唤醒,但是这两个方法必须在同步代码块synchronized里面,否则会报错,也不能先执行notify()方法后执行wait()方法,这样wait()方法执行完后就一直阻塞了,下面是例子。
1、正常使用的代码
public class WaitAndNotify {public static void main(String[] args) {Object lock = new Object();//wait()和notify()的使用必须要有锁,没有锁的话会报错new Thread(()->{synchronized (lock) {System.out.println(Thread.currentThread().getName()+"进来啦,然后被wait阻塞");try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"被唤醒啦");}},"t1").start();try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(()->{synchronized (lock) {System.out.println(Thread.currentThread().getName()+"notify唤醒了t1");lock.notify();}},"t2").start();}}
输出结果
t1进来啦,然后被wait阻塞t2notify唤醒了t1t1被唤醒啦
跟预想的一致。
2、wait()和notify()的使用必须要有锁,没有锁的话会报错
public class WaitAndNotify {public static void main(String[] args) {Object lock = new Object();//wait()和notify()的使用必须要有锁,没有锁的话会报错new Thread(()->{//synchronized (lock) {System.out.println(Thread.currentThread().getName()+"进来啦,然后被wait阻塞");try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"被唤醒啦");//}},"t1").start();try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(()->{//synchronized (lock) {System.out.println(Thread.currentThread().getName()+"notify唤醒了t1");lock.notify();//}},"t2").start();}}
t1进来啦,然后被wait阻塞Exception in thread "t1" java.lang.IllegalMonitorStateExceptionat java.lang.Object.wait(Native Method)at java.lang.Object.wait(Object.java:502)at mydemo.jdk.juc.wait.WaitAndNotify.lambda$0(WaitAndNotify.java:16)at mydemo.jdk.juc.wait.WaitAndNotify$$Lambda$1/989110044.run(Unknown Source)at java.lang.Thread.run(Thread.java:745)
3、如果先执行notify()后执行wait()则唤醒失败,会阻塞下去
public class WaitAndNotify {public static void main(String[] args) {Object lock = new Object();//wait()和notify()的使用必须要有锁,没有锁的话会报错new Thread(()->{try {//这里休息三秒,那么就是她唤醒线程先执行才能到这里的阻塞执行了Thread.sleep(3000);} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}synchronized (lock) {System.out.println(Thread.currentThread().getName()+"进来啦,然后被wait阻塞");try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"被唤醒啦");}},"t1").start();try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(()->{synchronized (lock) {System.out.println(Thread.currentThread().getName()+"notify唤醒了t1");lock.notify();}},"t2").start();}}
t2notify唤醒了t1t1进来啦,然后被wait阻塞
