Java线程间协作之等待与通知:wait、notify和notifyAll

介绍

在 Java 多线程编程中,wait、notify 和 notifyAll 是用于线程间通信的重要方法。它们是在 Object 类中定义的,因此每个 Java 对象都可以使用这些方法。本文将通过一个实际应用场景来介绍它们的使用。

  • wait:当线程调用 wait 方法时,它会释放对象的锁,并进入等待状态,直到被其他线程唤醒。
  • notify:notify 方法唤醒一个正在等待该对象锁的线程。如果有多个线程等待,则随机唤醒一个。
  • notifyAll:notifyAll 方法唤醒所有等待该对象锁的线程,让它们重新竞争锁。

实际应用

假设我们有一个简单的生产者-消费者问题。生产者线程负责生成数据,而消费者线程负责处理数据。为了协调两者的运行,我们需要使用 wait 和 notify 来管理它们之间的通信。

class ProducerConsumer {
    private final Queue<Integer> queue = new LinkedList<>();
    private final int MAX_CAPACITY = 10;
    private int producedCount = 0;
    // 停止生产
    private volatile boolean produceStop = false;

    public void produce() throws InterruptedException {
        int value = 1;
        while (!produceStop) {
            synchronized (this) {
                while (queue.size() == MAX_CAPACITY) {
                    System.out.println("Queue is full, waiting for consumer to consume...");
                    wait();
                }
                if (producedCount >= 50) {
                    produceStop = true;
                    break;
                }
                System.out.println("Thread: " + Thread.currentThread().getName() + " Produced: " + value);
                queue.add(value++);
                producedCount++;
                notify(); // Notify consumer thread
            }
            Thread.sleep(250);
        }
    }

    public void consume() throws InterruptedException {
        while (true){
            synchronized (this) {
                if (queue.isEmpty() && produceStop) {
                    System.out.println("Consumer thread finished.");
                    break;
                }
                while (queue.isEmpty()) {
                    System.out.println("Queue is empty, waiting for producer to produce...");
                    wait();
                }
                int value = queue.poll();
                System.out.println("Thread: " + Thread.currentThread().getName() + " Consumed: " + value);
                notify(); // Notify producer thread
            }
            Thread.sleep(500);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        ProducerConsumer pc = new ProducerConsumer();

        Thread producerThread = new Thread(() -> {
            try {
                pc.produce();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("Producer thread was interrupted.");
            }
        });

        Thread consumerThread = new Thread(() -> {
            try {
                pc.consume();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("Consumer thread was interrupted.");
            }
        });

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

程序解释

1、共享资源:我们使用一个 LinkedList 作为共享队列,最大容量为 10。
2、生产者方法:produce 方法在队列未满时添加数据,并在添加后调用 notify 唤醒消费者。
3、消费者方法:consume 方法在队列不为空时取出数据,并在取出后调用 notify 唤醒生产者。
4、同步块:synchronized 关键字用于确保对共享资源的线程安全访问。
5、等待条件:while 循环用于检查队列状态,以防止被错误唤醒(过早唤醒)。
6、while 循环:确保线程在每次被唤醒时都会重新检查条件,防止过早通知导致的错误操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值