wait()和notify()

线程同步机制
本文介绍了一个使用Java实现的简单线程同步案例,通过生产者-消费者模式演示了如何利用synchronized关键字、wait()及notify()方法来实现线程间的同步控制。

线程暂停:

Thread.wait()需要notify()方法激活,notify是Object类提供的方法,只能激活当前第一个上锁状态的线程,或者优先级高的线程,而notifuAll可以全部解锁

以下是实例:

//生产类
class    DataProvider implements Runnable {
    private Data data;
    public DataProvider(Data data) {
        this.data = data;
    }
    public void run() {
        for(int x = 0; x < 100; x ++) {
            if(x % 2 == 0) {
                this.data.set("苹果","水果");    //设置产品1
            } else {
                this.data.set("苹果","手机");    //设置产品2
            }
        }
    }
}
//消费者类
class    DataConsumer implements Runnable {
    private Data data;
    public DataConsumer(Data data) {
        this.data = data;
    }
    public void run() {
        for(int x =0; x < 50; x ++) {
            try {
                Thread.sleep(10);
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
            this.data.get();    //每10ms获取从中介处获取产品
        }
    }
}
//中介类
class    Data {
    private String title;    //商品名
    private String note;    //商品标签
    private boolean flag = false;    //生产消费控制

    public synchronized void set(String title,String note) {
        while(this.flag == true) {        //商品流通时不补给
            try{
                super.wait();    //继承Object类
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
//        商品不流通时补给
        this.title = title;    
        this.note = note;
//        补给完毕开始流通        
        this.flag = true;    
        super.notify();    //给第一个锁解锁(当前运行消费者类的线程上锁状态)
    }
    
    public synchronized void get() {
        while(flag == false) {    //补给时不能购买
            try {
                super.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
//        不补给时可以购买
        System.out.println(this.title+" = "+this.note);
        this.flag = false;    //购买完毕开始补给
        super.notify();    //给上锁的解锁(当前运行生产者类的线程上锁状态)
    }
}


public class TestDemo{
    public static void main(String[] args)    {
        Data data = new Data();    //实例化中介类
        new Thread(new DataProvider(data)).start();    //把中介类设置成生产类的成员,用线程启动生产类
        new Thread(new DataConsumer(data)).start();    //把同一个中介类设置成消费者类的成员,用线程启动
    }
}


在Java多线程编程中,`wait()` `notify()` 是用于线程间通信的重要方法,它们定义在 `Object` 类中,并且必须在同步上下文中(如 `synchronized` 方法或代码块)中使用。这两个方法的主要作用是协调多个线程的执行顺序,确保线程之间可以安全地共享资源。 ### wait() 方法 `wait()` 方法的作用是使当前线程进入等待状态,直到其他线程调用该对象上的 `notify()` 或 `notifyAll()` 方法来唤醒它。调用 `wait()` 时,当前线程会释放持有的对象锁,并进入该对象的等待队列中[^4]。 一个典型的使用模式如下: ```java synchronized (lock) { while (!condition) { lock.wait(); } // 执行后续操作 } ``` 在此模式中,线程会在条件不满足时通过 `wait()` 进入等待状态,并在条件发生变化时被唤醒继续执行。 ### notify() 方法 `notify()` 方法用于唤醒在指定对象上等待的一个线程。如果有多个线程在等待,则由线程调度器随机选择其中一个进行唤醒。需要注意的是,调用 `notify()` 后,当前线程不会立即释放对象锁,而是要等到其所在的同步代码块或方法执行完毕后才会释放锁[^1]。 以下是一个简单的示例说明 `notify()` 的使用: ```java public class NotifyExample { public static void main(String[] args) { Object lock = new Object(); Thread t1 = new Thread(() -> { synchronized (lock) { System.out.println("t1 开始等待"); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 被唤醒"); } }); Thread t2 = new Thread(() -> { synchronized (lock) { System.out.println("t2 准备通知"); lock.notify(); System.out.println("t2 已通知"); } }); t1.start(); try { Thread.sleep(1000); // 确保 t1 先进入等待状态 } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } } ``` 在这个例子中,线程 `t1` 在进入同步代码块后调用 `wait()` 方法并释放锁,而线程 `t2` 在随后调用 `notify()` 来唤醒 `t1`。 ### 使用注意事项 - **必须在同步环境中使用**:`wait()` `notify()` 必须在 `synchronized` 方法或代码块中调用,否则会抛出 `IllegalMonitorStateException` 异常[^2]。 - **避免虚假唤醒**:通常建议将 `wait()` 放在一个循环中检查条件是否满足,以防止线程在没有收到通知的情况下被唤醒。 - **notify()notifyAll() 的区别**:`notify()` 只唤醒一个等待线程,而 `notifyAll()` 唤醒所有等待线程,适用于需要处理多个线程竞争的情况[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值