Java 线程wait, notify and notifyAll 示例

本文详细介绍了Java中Object类提供的wait、notify和notifyAll方法的使用,通过一个简单的生产者消费者问题示例,展示了如何在多线程环境下通过这三个方法维护资源的锁状态。实例包括定义了一个Message类用于存储消息,Waiter类用于等待通知,Notifier类用于设置消息并通知等待线程,最后WaitNotifyTest类启动线程进行测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example
Java的Object类提供了三个final方法来在维护多线程中资源的锁状态。它们是wait(), notify() 和 notifyAll()。使用这三个方法来维护资源的线程必须有该资源的monitor(使用synchronized关键字,译者注),否则会抛出java.lang.IllegalMonitorStateException.
wait
对象的wait方法有三种调用方式,第一种当前线程会无限等待其他线程调用该对象的notify或者notifyAll方法来唤醒它所在的线程;另外两个会令当前线程等待特定的时间然后唤醒。
notify
notify方法每次只唤醒一个等待该object的线程。所以如果多个线程在等待这个object,这个方法只会唤醒其中的一个。唤醒哪个取决于系统实现的线程管理器。
notifyAll
notifyAll方法唤醒等待该object的所有线程,哪个先唤醒取决于操作系统。
这些方法可以用来实现 producer-consumer-problem (生产者消费者问题),消费者线程等待队列中的对象,生产者线程向队列中放入对象并通知等待的线程。
让我们看一个多线程操作同一个对象的例子。
Message
下面是一个java bean类,线程会调用这个类的wait和notify方法。
Message.java

package com.journaldev.concurrency;
public class Message {
    private String msg;
    public Message(String str){
        this.msg=str;
    }
    public String getMsg() {
        returnmsg;
    }
    public void setMsg(String str) {
        this.msg=str;
    }
}

Waiter
该类会等待别的线程调用notify方法来唤醒自己。注意Waiter线程使用synchronized 块拥有了Message的monitor。

package com.journaldev.concurrency;
public class Waiter implements Runnable{
    private Message msg;
    public Waiter(Message m){
        this.msg=m;
    }
    @Override
    publicvoidrun() {
        String name = Thread.currentThread().getName();
        synchronized(msg) {
            try{
                System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
                msg.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
            //process the message now
            System.out.println(name+" processed: "+msg.getMsg());
        }
    }
}

Notifier
该类会对Message对象进行处理,然后调用notify方法来唤醒等待Message对象的线程。它同样用synchronized块拥有了对Message的管理。
Notifier.java

package com.journaldev.concurrency;
public class Notifier implements Runnable {
    private Message msg;
    public Notifier(Message msg) {
        this.msg = msg;
    }
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name+" started");
        try{
            Thread.sleep(1000);
            synchronized(msg) {
                msg.setMsg(name+" Notifier work done");
                msg.notify();
                // msg.notifyAll();
            }
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
    }
}

WaitNotifyTest
该类会创建并运行多个Waiter线程和一个Notifer线程。
WaitNotifyTest.java

package com.journaldev.concurrency;
public class WaitNotifyTest {
    public static void main(String[] args) {
        Message msg = newMessage("process it");
        Waiter waiter = new Waiter(msg);
        new Thread(waiter,"waiter").start();

        Waiter waiter1 = new Waiter(msg);
        new Thread(waiter1, "waiter1").start();

        Notifier notifier = new Notifier(msg);
        new Thread(notifier, "notifier").start();
        System.out.println("All the threads are started");
    }
}

运行上面的程序,会看到下面的运行结果,程序不会结束因为有两个线程在等待Message对象但是notify方法只会唤醒其中的一个,另外一个依然在等待被唤醒。

waiter waiting to get notified at time:1356318734009
waiter1 waiting to get notified at time:1356318734010
All the threads are started
notifier started
waiter waiter thread got notified at time:1356318735011
waiter processed: notifier Notifier work done

注释掉notify(),使用notifyAll()方法,会出现下面的运行结果。

waiter waiting to get notified at time:1356318917118
waiter1 waiting to get notified at time:1356318917118
All the threads are started
notifier started
waiter1 waiter thread got notified at time:1356318918120
waiter1 processed: notifier Notifier work done
waiter waiter thread got notified at time:1356318918120
waiter processed: notifier Notifier work done

notifyAll唤醒了所有的等待线程,程序结束。


译者注:
1 有哪些更实际的例子呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值