在 Java 中,wait
与 notify
方法是用于线程之间通信的重要工具。它们被用于实现线程的等待与唤醒,以及线程之间的协作。本节将深入介绍这两个方法的使用方式、作用以及一些注意事项。
wait
方法
wait
方法是 java.lang.Object
类的一个实例方法,它用于使当前线程进入等待状态,直到其他线程调用相同对象上的 notify
或 notifyAll
方法来唤醒它。wait
方法通常与 synchronized
关键字一起使用,以确保线程在等待时不会发生竞态条件。
wait
方法的语法
java
public final void wait() throws InterruptedException
-
wait
方法没有参数,它将当前线程置于等待状态,直到其他线程调用相同对象上的notify
或notifyAll
方法。 -
InterruptedException
异常表示如果线程在等待过程中被中断,会抛出该异常。
wait
方法的示例
以下是一个简单的示例,演示如何使用 wait
方法等待其他线程的通知:
java
public class WaitNotifyExample {
public static void main(String[] args) {
final Object lock = new Object();
Thread waiterThread = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Waiter: Waiting for notification...");
lock.wait(); // 进入等待状态
System.out.println("Waiter: Got notified!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread notifierThread = new Thread(() -> {
synchronized (lock) {
try {
Thread.sleep(2000); // 模拟一些操作
System.out.println("Notifier: Notifying waiter...");
lock.notify(); // 唤醒等待的线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
waiterThread.start();
notifierThread.start();
}
}
在这个示例中,waiterThread
在锁定 lock
对象后调用 lock.wait()
进入等待状态,等待 notifierThread
唤醒它。
notify
方法与 notifyAll
方法
notify
方法和 notifyAll
方法都用于唤醒等待在同一个对象上的线程。主要区别在于:
-
notify
方法只会唤醒一个等待线程(无法确定是哪一个),通常用于特定条件下只需唤醒一个线程的情况。 -
notifyAll
方法会唤醒所有等待线程,通常用于多个线程都需要同时被唤醒的情况。
notify
方法的语法
java
public final void notify()
notify
方法唤醒在相同对象上等待的一个线程。
notifyAll
方法的语法
java
public final void notifyAll()
notifyAll
方法唤醒在相同对象上等待的所有线程。
notify
与 notifyAll
方法的示例
以下示例演示了如何使用 notify
方法唤醒等待线程:
java
public class NotifyExample {
public static void main(String[] args) {
final Object lock = new Object();
Thread waiterThread1 = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Waiter 1: Waiting for notification...");
lock.wait();
System.out.println("Waiter 1: Got notified!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread waiterThread2 = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Waiter 2: Waiting for notification...");
lock.wait();
System.out.println("Waiter 2: Got notified!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread notifierThread = new Thread(() -> {
synchronized (lock) {
try {
Thread.sleep(2000);
System.out.println("Notifier: Notifying waiters...");
lock.notify(); // 唤醒等待的线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
waiterThread1.start();
waiterThread2.start();
notifierThread.start();
}
}
在这个示例中,notifierThread
在锁定 lock
对象后调用 lock.notify()
唤醒一个等待线程,可以是 waiterThread1
或 waiterThread2
中的任何一个。
注意事项
在使用 wait
、notify
和 notifyAll
方法时,需要注意以下事项:
-
这些方法必须在
synchronized
块内调用,以确保线程安全。 -
线程在调用
wait
方法时会释放锁,使得其他线程可以获得锁并执行。当线程被唤醒时,它会重新尝试获得锁。 -
使用
wait
方法时,通常需要将它包装在一个循环中,以防止虚假唤醒(即在没有被通知的情况下线程被唤醒)。 -
notify
方法和notifyAll
方法不会释放锁,它们只是唤醒等待线程,等待线程被唤醒后需要重新竞争锁。 -
notify
方法通常用于只唤醒一个线程的情况,而notifyAll
方法用于唤醒所有等待线程的情况。 -
在多线程编程中,要小心死锁和竞态条件等问题,确保线程通信的安全性和正确性。
总结
希望本文能够帮助您更好地理解 wait
与 notify
方法在 Java 多线程编程中的作用和用法。通过合理地使用这些方法,可以实现线程之间的协作与通信,编写出更可靠的多线程程序。