在Java中,wait
、notify/notifyAll
和 join
方法是实现线程间协作的常用工具。这些方法主要用于协调线程的执行顺序和共享资源的访问。下面是这些方法的详细解释和示例代码。
1. wait 和 notify/notifyAll
wait
和 notify/notifyAll
方法用于线程间的通信,主要用来在线程间传递信号以实现协作。这些方法必须在同步块或同步方法中调用,否则会抛出 IllegalMonitorStateException
异常。
- wait:使当前线程等待,直到另一个线程调用
notify
或notifyAll
方法。 - notify:唤醒一个正在等待的线程。
- notifyAll:唤醒所有正在等待的线程。
示例代码
public class WaitNotifyExample {
private final Object lock = new Object();
private boolean condition = false;
public static void main(String[] args) {
WaitNotifyExample example = new WaitNotifyExample();
Thread thread1 = new Thread(example::waitForCondition);
Thread thread2 = new Thread(example::changeCondition);
thread1.start();
thread2.start();
}
public void waitForCondition() {
synchronized (lock) {
while (!condition) {
try {
System.out.println("Thread 1 is waiting for condition to be true.");
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println("Condition is true. Thread 1 proceeds.");
}
}
public void changeCondition() {
synchronized (lock) {
try {
Thread.sleep(1000); // Simulate some work
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
condition = true;
System.out.println("Condition set to true. Thread 2 notifies.");
lock.notifyAll();
}
}
}
在这个例子中,waitForCondition
方法中的线程1会等待,直到 condition
为 true
。changeCondition
方法中的线程2会更改 condition
并调用 notifyAll
唤醒所有等待的线程。
2. join
join
方法用于等待另一个线程完成。当一个线程调用另一个线程的 join
方法时,当前线程会被阻塞,直到被调用的线程执行完毕。
示例代码
public class JoinExample {
public static void main(String[] args) {
Thread thread1 = new Thread(new Worker(), "Thread-1");
Thread thread2 = new Thread(new Worker(), "Thread-2");
thread1.start();
try {
thread1.join(); // Main thread waits for thread1 to finish
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
thread2.start();
try {
thread2.join(); // Main thread waits for thread2 to finish
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Both threads have finished execution.");
}
static class Worker implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}
在这个例子中,主线程会等待 thread1
完成后再启动 thread2
,并等待 thread2
完成后才继续执行。这确保了线程按顺序执行。
总结
- wait:使当前线程等待,直到另一个线程调用
notify
或notifyAll
。 - notify:唤醒一个等待的线程。
- notifyAll:唤醒所有等待的线程。
- join:等待另一个线程完成。
这些方法在多线程编程中非常重要,它们提供了线程间协作和通信的机制,确保线程能够正确地共享资源和执行顺序。通过合理使用这些方法,可以避免竞争条件和数据不一致的问题。