1.每个Java对象都有一个监视器(monitor),它是用来控制对该对象的访问的。一个线程要想进入某个对象的监视器区域,必须先获得该对象的锁。然后可以通过wait方法来释放该对象的锁并进入等待状态,直到其他线程调用notify或notifyAll方法唤醒它。notify方法会选择一个等待该对象的线程进行唤醒,而notifyAll方法会唤醒所有等待该对象的线程。
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread t3 = new Thread(() -> {
synchronized (lock) {
for (int i = 0; i < 1000; i = i + 2) {
lock.notify(); //换醒一个等待lock对象的线程进行唤醒,这里只有两个线程,所以这里唤醒的是t4线程,不过t3线程并没有释放锁,所以T4线程只是进入了可运行状态 1
System.out.println(i);
try {
lock.wait(); // t3进入了等待队列,并且释放锁lock,这时候t4就可以获取锁执行了 2
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
lock.notifyAll();
}
});
Thread t4 = new Thread(() -> {
synchronized (lock) {
for (int i = 1; i < 1000; i = i + 2) {
lock.notify(); // 3. 唤醒t3线程,使其进入可执行状态
System.out.println(i);
try {
lock.wait(); // t4进入等待状态,释放lock锁,
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
lock.notifyAll(); // t3和t4交替执行完后,都进入了等待
}
});
t3.start();
Thread.sleep(1000);
t4.start();
}
运行结果:
wait和notify方法只能在同步方法或同步块中使用。如果一个线程在调用wait方法前没有获得该对象的锁,会抛出IllegalMonitorStateException异常。