详解Java的wait()方法:使当前线程等待

  • Post category:Java

Java中的wait()方法用于线程间的协作,其作用是将当前线程挂起,等待其他线程唤醒。

语法格式

public final void wait() throws InterruptedException
public final native void wait(long timeout) throws InterruptedException
public final void wait(long timeout, int nanos) throws InterruptedException

wait()方法的用法

wait()方法必须要在synchronized块中调用,否则会抛出IllegalMonitorStateException异常。当线程进入synchronized块后,如果调用wait()方法,则当前线程会被挂起,直到其他线程调用notify()或notifyAll()方法唤醒该线程。

在调用wait()方法后,当前线程释放所持有的锁,其他线程才有机会获取该锁。

wait()方法可以重载,可以指定等待的最长时间,如果时间到达后仍未被其他线程唤醒,会自动唤醒当前线程。

wait()方法的示例

示例1:使用wait()和notify()协同线程

下面的示例展示了如何使用wait()和notify()协同两个线程。

public class WaitAndNotifyTest {
    public static void main(String[] args) {
        final Object lock = new Object();

        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        System.out.println(Thread.currentThread().getName() + "开始等待...");
                        lock.wait();
                        System.out.println(Thread.currentThread().getName() + "等待结束...");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "线程A");

        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName() + "开始唤醒等待线程...");
                    lock.notify();
                    System.out.println(Thread.currentThread().getName() + "完成唤醒等待线程...");
                }
            }
        }, "线程B");

        threadA.start();
        threadB.start();
    }
}

输出结果:

线程A开始等待...
线程B开始唤醒等待线程...
线程B完成唤醒等待线程...
线程A等待结束...

在本例中,线程A等待线程B发出notify(),线程B发出notify()之后,线程A才会继续运行。

示例2:使用wait()和notifyAll()协同多个线程

下面的示例展示了如何使用wait()和notifyAll()协同多个线程。

public class WaitAndNotifyAllTest {
    public static void main(String[] args) {
        final Object lock = new Object();

        Thread[] threads = new Thread[5];

        for (int i = 0; i < 5; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (lock) {
                        try {
                            System.out.println(Thread.currentThread().getName() + "开始等待...");
                            lock.wait();
                            System.out.println(Thread.currentThread().getName() + "等待结束...");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }, "线程" + (i + 1));
            threads[i].start();
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName() + "开始唤醒等待线程...");
                    lock.notifyAll();
                    System.out.println(Thread.currentThread().getName() + "完成唤醒等待线程...");
                }
            }
        }, "线程A");
        threadA.start();
    }
}

输出结果:

线程1开始等待...
线程2开始等待...
线程3开始等待...
线程4开始等待...
线程5开始等待...
线程A开始唤醒等待线程...
线程A完成唤醒等待线程...
线程1等待结束...
线程2等待结束...
线程3等待结束...
线程4等待结束...
线程5等待结束...

在本例中,多个线程在同一个锁lock上等待,线程A发出notifyAll()之后,所有线程都被唤醒,最终所有线程都完成了等待。