前言
在Java中,若要实现程序的等待唤醒机制,可以使用jdk提供的wait()等待、notify()或者notifyAll()唤醒方法
等待唤醒
用法
使用wait()和notify()实现程序等待唤醒
public class LockDemo {
static final Object object = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + ":开始执行");
try {
// 使当前线程等待
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":执行结束");
}
}, "A").start();
new Thread(() -> {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + "==>开始唤醒");
// 使当前线程唤醒
object.notify();
System.out.println(Thread.currentThread().getName() + ":唤醒结束");
}
}, "B").start();
}
}
notify()方法只能唤醒一个wait(),如果存在多个的话,只能唤醒一个,如
public class Lock2Demo {
static Object object = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + ":开始执行");
try {
// 使当前线程等待
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":执行结束");
}
}, "A").start();
new Thread(() -> {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + ":开始执行");
try {
// 使当前线程等待
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":执行结束");
}
}, "C").start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
new Thread(() -> {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + ":开始唤醒");
// 使当前线程唤醒
object.notify();
System.out.println(Thread.currentThread().getName() + ":唤醒结束");
}
}, "B").start();
}
}
输出结果为
要唤醒多个的话,使用notifyAll()方法,如
public class Lock2Demo {
static Object object = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + ":开始执行");
try {
// 使当前线程等待
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":执行结束");
}
}, "A").start();
new Thread(() -> {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + ":开始执行");
try {
// 使当前线程等待
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":执行结束");
}
}, "C").start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
new Thread(() -> {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + ":开始唤醒");
// 使当前线程唤醒
object.notifyAll();
System.out.println(Thread.currentThread().getName() + ":唤醒结束");
}
}, "B").start();
}
}
输出结果为
备注,wait()、notify()或者notifyAll()这三个方法,必须要加锁synchronized()修饰,否则会报错
public class Lock3Demo {
static Object object = new Object();
public static void main(String[] args) {
new Thread(() -> {
try {
// 使当前线程等待
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + ":开始唤醒");
// 使当前线程唤醒
object.notifyAll();
System.out.println(Thread.currentThread().getName() + ":唤醒结束");
}, "B").start();
}
}
会报以下错误
必须配合synchronized使用,否则抛出IllegalMonitorStateException异常
总结
合理使用Java的等待唤醒机制,可以更好的编码,而且等待唤醒调用顺序不能改变,必须加锁修饰