【JAVA】wait和notify用法,附生产/消费模型

关于wait和notify的用法,网上已经有很多详细解释了,我只是简单的总结下。

  1. wait用于释放锁A,并让wait所在的线程阻塞。除非被持有锁A的其它线程执行notify来唤醒,它才能重新"活"过来。
  2. notify用于唤醒因为等待锁A而阻塞的线程,让它们做好竞争锁A的准备。如果有多个线程因等待锁A而被阻塞,notify只唤醒一个,唤醒所有用notifyAll。
  3. 参考下面的线程状态图,对理解wait和notify有很大的帮助。

总结:

  • wait和notify通常和synchronized(obj)一起用,注意obj应该是多线程共用的同一个对象(即多线程状态下各个线程要竞争这个对象锁),如果不是同一个对象,那么就不能控制并发了,wait和notify也不能有效的相互作用,因为根本就不是操作同一个对象。可以参考文章最后的Demo样例。
  • wait和notify来自synchronized中的obj,而不是别的地方,obj只是作为一个对象锁,供各个线程竞争。

--------------------------------

线程状态图(一样的东西,只是中英文描述而已):

--------------------------------

最后上生产/消费模型的代码:

基类

public abstract class Person implements Runnable{

    public static Object lock = new Object();
    public static int ticket = 0;

    public abstract void execute();
}


---

生产者

public class Producer extends Person {
    @Override
    public void execute() {
        synchronized (lock) {
            while (true){
                if (ticket == 0) {
                    while(ticket<10) {
                        System.out.println("生产中,当前数量:"+ticket);
                        ticket++;
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("生产完毕,当前数量:"+ticket);
                    lock.notify();
                }else{
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    @Override
    public void run() {
        execute();
    }
}

---

消费者

public class Consumer extends Person {
    @Override
    public void execute() {
        synchronized (lock){
            while (true){
                if(ticket==0){
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else{
                    System.out.println("消耗中,总数量:"+ticket);
                    while (ticket>0){
                        System.out.println("消耗中,当前数量:"+ticket);
                        ticket--;
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("消耗完成,当前数量:"+ticket);
                    lock.notify();
                }
            }
        }
    }

    @Override
    public void run() {
        execute();
    }
}


---

运行Demo

 

public class Demo {

    public static void main(String[] args){

        //设置先生产还是先消费,默认ticket是0先生产。
        //ticket是静态的,所以可以这么设置,虽然不是很规范。
        new Producer().ticket = 6;

        Thread pro = new Thread(new Producer());
        Thread con = new Thread(new Consumer());
        pro.start();
        con.start();
    }
}

重要的事再提一遍:

总结:

  • wait和notify通常和synchronized(obj)一起用,注意obj应该是多线程共用的同一个对象(即多线程状态下各个线程要竞争这个对象锁),如果不是同一个对象,那么就不能控制并发了,wait和notify也不能有效的相互作用,因为根本就不是操作同一个对象。可以参考文章最后的Demo样例。
  • wait和notify来自synchronized中的obj,而不是别的地方,obj只是作为一个对象锁,供各个线程竞争。

 

 

 

-----------------------------------------------------

请尊重作者劳动成果,

转载请注明出处

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值