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唤醒了t1
t1被唤醒啦
跟预想的一致。
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.IllegalMonitorStateException
at 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 block
e1.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唤醒了t1
t1进来啦,然后被wait阻塞