返回

揭秘Object中的wait()和notify()方法:揭开线程通信与同步的神秘面纱

后端

线程通信与同步:揭秘wait()和notify()的神奇力量

子标题 1:wait()方法的魅力

想象一下,你正与朋友轮流玩一场游戏。当你等待朋友的回合时,你不想一直坐在那里无所事事,所以你决定先去休息一下。一旦朋友完成回合,他就会叫醒你,你可以继续游戏。这种轮流机制本质上就是wait()方法所做的。

wait()方法让线程进入一种休眠状态,暂停其执行。这就好比在你朋友的回合时,你选择休息一样。线程保持休眠,直到其他线程调用notify()或notifyAll()方法将其唤醒。

子标题 2:notify()和notifyAll()方法的魔力

当朋友完成回合,准备让你继续玩时,他就会对你大喊:“轮到你啦!”这就是notify()方法所做的。它会随机唤醒一个处于休眠状态的线程。

而notifyAll()方法则更像是集体叫醒。它会将所有处于休眠状态的线程都叫醒,就像朋友对你们所有玩家大喊:“大家继续玩!”

子标题 3:wait()和notify()的协同工作

为了让wait()和notify()方法协同工作,我们需要一个“锁对象”。这个锁对象可以是任何对象,它用于协调线程的访问。

在我们的游戏示例中,锁对象可以是游戏本身。当一个线程(即玩家)想要玩游戏时,它必须先获得锁对象。如果锁对象被另一个线程(即其他玩家)持有,那么该线程必须等待,直到持有锁的线程释放它。

子标题 4:实战案例:生产者-消费者模型

让我们用一个经典的生产者-消费者模型来展示wait()和notify()方法的实际应用。在这个模型中,生产者线程不断生成数据,而消费者线程不断消费数据。

为了确保数据生产和消费的平稳进行,我们使用wait()和notify()方法来协调这两个线程。当生产者线程没有数据可生产时,它会调用wait()方法进入休眠状态,直到消费者线程消费了数据并调用notify()方法唤醒它。

同样,当消费者线程没有数据可消费时,它也会调用wait()方法进入休眠状态,直到生产者线程生产了数据并调用notify()方法唤醒它。

通过这种方式,生产者线程和消费者线程可以协同工作,避免数据生产和消费之间的不一致。

代码示例:

public class ProducerConsumer {

    private Object lock = new Object();
    private boolean dataReady = false;

    public void producer() {
        synchronized (lock) {
            while (!dataReady) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 生产数据
            dataReady = false;
            lock.notifyAll();
        }
    }

    public void consumer() {
        synchronized (lock) {
            while (!dataReady) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 消费数据
            dataReady = false;
            lock.notifyAll();
        }
    }

    public static void main(String[] args) {
        ProducerConsumer pc = new ProducerConsumer();
        Thread producerThread = new Thread(pc::producer);
        Thread consumerThread = new Thread(pc::consumer);

        producerThread.start();
        consumerThread.start();
    }
}

常见问题解答

1. 为什么需要wait()和notify()方法?

wait()和notify()方法允许线程之间进行通信和同步,防止数据不一致和死锁。

2. wait()和notify()方法有何区别?

wait()方法使线程进入休眠状态,直到被notify()或notifyAll()方法唤醒。notify()方法随机唤醒一个等待的线程,而notifyAll()方法唤醒所有等待的线程。

3. 什么是锁对象?

锁对象用于协调线程对共享资源的访问,防止多个线程同时访问同一个资源。

4. wait()和notify()方法应该在哪里使用?

wait()和notify()方法应该在需要协调多个线程访问共享资源的情况下使用,例如生产者-消费者模型。

5. 除了wait()和notify()之外,还有其他线程通信和同步的方法吗?

是的,还有其他方法,例如锁、信号量和条件变量。