1.等待和唤醒是同一个对象
2.notify只会唤醒一个线程
使用角度
1.Object.wait() 会抛出 InterruptedException
2.调用object.wait() 必须首先对object(monitor lock) 进行加锁
class Main{
private static Object object = new Object();
private static class AThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("A 在扫地");
}
try {
synchronized (object) {
object.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10; i++) {
System.out.println("A 正在擦桌子");
}
}
}
public static void main(String[] args) {
Thread aThread = new AThread();
aThread.start();
Scanner scanner = new Scanner(System.in);
System.out.println("随便输入什么,A去擦桌子");
scanner.nextLine();
synchronized (object){
object.notify();
}
}
}
sync(object){
object.wait
}
调用到wait 释放锁,进入waiting状态,从等待集出来只会,还会再加一次锁(请求锁)
注意事项:
- 必须先加锁,才能调用wait
- wait和notify必须是同一对象
- wait会释放锁(等待在哪个对象上,释放哪个锁)
- wait返回之前,需要再次加锁
- notify只会唤醒一个,并且是随机
- notifyAll会唤醒所有的
- wait和notify之间的时序很重要
顺序打印
public class PrintInOrder {
private static int i = 0;
public synchronized void first() throws InterruptedException {
if (i == 0) {
System.out.println("One");
i = 1;
notifyAll();
}
wait();
}
public synchronized void second() throws InterruptedException {
if (i == 1) {
System.out.println("two");
i = 2;
notifyAll();
}
wait();
}
public synchronized void third() throws InterruptedException {
if (i == 2) {
System.out.println("three");
i = 0;
notifyAll();
}
wait();
}
private static class printOne extends Thread{
PrintInOrder object;
public printOne(PrintInOrder object) {
this.object = object;
}
@Override
public void run() {
while (true){
try {
object.first();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class PrintTwo extends Thread{
PrintInOrder object;
public PrintTwo(PrintInOrder object) {
this.object = object;
}
@Override
public void run() {
while (true){
try {
object.second();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class PrintThree extends Thread{
PrintInOrder object;
public PrintThree(PrintInOrder object) {
this.object = object;
}
@Override
public void run() {
while (true){
try {
object.third();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
PrintInOrder object = new PrintInOrder();
Thread t1 = new printOne(object);
t1.start();
Thread t2 = new PrintTwo(object);
t2.start();
Thread t3 = new PrintThree(object);
t3.start();
}
}