1、所属类和包:
wait 和notify 属于Object 类,用于基本的对象监视器机制,而且它们必须在同步块或同步方法中使用。park 和unpark 属于sun.misc.Unsafe 类,提供了更底层的线程挂起和恢复操作。它们可以在任何地方使用,不需要在同步块中。await 和signal 属于java.util.concurrent.locks.Condition 接口,通常在ReentrantLock 的锁保护下使用。它们提供了更高级别的、更灵活的线程协作机制。
2、唤醒方式:
notify 只能唤醒等待在同一对象监视器上的一个线程。(调用notify 方法而没有任何等待的线程会引发IllegalMonitorStateException 异常)notifyAll 唤醒等待在同一对象监视器上的所有线程。(调用notifyAll 方法而没有任何等待的线程是不会引发异常的)unpark 可以指定唤醒哪个线程,因为需要传递线程对象作为参数。(当无park时执行unpark 不会异常,可以先执行unpark再执行park)signal 只能唤醒等待在相同Condition 对象上的一个线程(signal 唤醒等待在相同Condition 对象上的所有线程)。await 和signal 可以通过使用多个Condition 对象来实现更灵活的唤醒策略。
3、用法示例:
wait 和 notify:
synchronized (lock) { while (conditionIsNotMet()) { lock.wait(); } // 执行满足条件时的操作 lock.notify(); }
park 和 unpark:
import java.util.concurrent.locks.LockSupport; public class ParkUnparkExample { public static void main(String[] args) { Thread thread = new Thread(() -> { System.out.println(Thread.currentThread().getName() + " - Before park"); // 调用park,线程将被阻塞 LockSupport.park(); System.out.println(Thread.currentThread().getName() + " - After park"); }); // 启动线程 thread.start(); try { Thread.sleep(2000); // 主线程等待一段时间 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " - Before unpark"); // 调用unpark,唤醒指定线程 LockSupport.unpark(thread); System.out.println(Thread.currentThread().getName() + " - After unpark"); } }
await 和 signal:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class AwaitSignalExample { private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); private boolean conditionMet = false; public void waitForCondition() throws InterruptedException { lock.lock(); try { while (!conditionMet) { System.out.println(Thread.currentThread().getName() + " - Waiting for condition"); condition.await(); } System.out.println(Thread.currentThread().getName() + " - Condition is met"); } finally { lock.unlock(); } } public void signalCondition() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + " - Signaling condition"); conditionMet = true; condition.signal(); } finally { lock.unlock(); } } public static void main(String[] args) { AwaitSignalExample example = new AwaitSignalExample(); Thread waitingThread = new Thread(() -> { try { example.waitForCondition(); } catch (InterruptedException e) { e.printStackTrace(); } }, "WaitingThread"); Thread signalingThread = new Thread(example::signalCondition, "SignalingThread"); waitingThread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } signalingThread.start(); } }