本文深入探讨了Java并发编程中的两个重要方法——notify和notifyAll的区别与联系,旨在帮助开发者理解如何在多线程环境下正确使用它们。
在Java多线程编程中,`notify` 和 `notifyAll` 是用于线程间通信的关键方法,在处理同步机制时尤为关键。这两个方法定义于 `Object` 类,并适用于所有 Java 对象。
了解 Java 的同步机制是必要的:当一个线程进入带有 `synchronized` 关键字的代码块或方法,它将获得该对象的锁(即成为此对象监视器的所有者)。同一时间仅允许一个线程持有这个锁。其他试图获取相同资源的线程会被阻塞,直至锁被释放。
`notify()` 和 `notifyAll()` 方法用于唤醒在特定对象上等待的线程:
1. **`notify()`**:随机选择并唤醒单个处于该对象等待队列中的某个线程。然而,只有当此线程重新获得锁时才能继续执行同步代码块。
2. **`notifyAll()`**:会同时唤醒所有在特定对象上等待的线程。这些被唤醒的线程同样需要竞争获取锁的机会;只有一个成功获取到锁后方能执行。
示例中,创建了一个可运行类 `R`,其中每个实例在线程同步代码块内调用 `wait()` 方法进行等待,并打印消息随后休眠30秒。在主程序里,10个这样的线程被启动。主程序经过5秒钟的延迟后对共享对象 `obj` 调用了 `notifyAll()` ,这将唤醒所有处于等待状态下的线程。
尽管使用了 `notifyAll()`, 只有成功获取锁的那个线程能够继续执行;其他仍需等待直到锁再次释放。因此,即使被全部唤醒,只有获得锁的单一线程能在短时间内运行,其余则持续等待机会重新竞争锁资源。
总结来说:`notify()` 和 `notifyAll()` 用于终止那些处于等待状态下的线程,但前者仅随机选择一个进行唤醒而后者则是所有;在多线程环境中正确使用这两个方法能够有效地协调各线程间的交互,并确保并发控制的准确性。注意这些操作必须在持有锁的情况下执行(即同步代码块或方法内),否则将引发 `IllegalMonitorStateException` 异常。