Java并发编程(二):wait() notify() notifyAll()

wait()notify()notifyAll()方法是 Object 的三个方法。

wait()使当前线程进入等待状态,直到:

  • 其它线程调用notify()方法或者notifyAll()方法
  • 其它线程中断了当前线程
  • 到了指定的 wait 时间

它的使用方式是在一个循环中

synchronized (obj) {
    // 条件不满足
    while (condition does not hold) {
        obj.wait();
    }
    // 执行满足条件的代码
}

调用wait()当前线程会释放锁,让出CPU进入等待状态。notify()notifyAll()都是唤醒当前正在等待的线程。而notify()只唤醒其中一个线程,唤醒的线程是随机的,notifyAll()方法则是唤醒所有正在等待的线程。线程被唤醒后并不会马上执行任务,由哪个线程去执行任务是由系统调度。wait()notify()notifyAll()需要被包括在syncronized代码块或者方法中。

使用wait()notify()notifyAll()实现一个消费者与生产者模式。

消费者与生产者有一个共同的容器,消费者从容器中取出数据消费,生产者生产数据后放入容器。当容器为空时消费者阻塞,同时生产者生产数据;当容器满时,生产者堵塞不再生产,通知消费者消费。

容器

public class Container {
    private static final int MAX_SIZE = 5;
    private final LinkedList<Object> list = new LinkedList<>();

    // 生产
    public void product() {
        synchronized (list) {
            while (list.size() >= MAX_SIZE) { // 容器里面的数据达到了最大,生产者就进入等待状态
                try {
                    System.out.println("容器装满了,有" + list.size() + "条数据    --" + Thread.currentThread().getName());
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.addFirst(new Object());

            System.out.println("+++++生产者生产了一条数据,有" + list.size() + "条数据   --" + Thread.currentThread().getName());
            list.notifyAll();
        }
    }

    public void consume() {
        synchronized (list) {
            while (list.size() <= 0) { // 容器里面数据为空,消费者就进入等待状态
                try {
                    System.out.println("容器没有数据了   --" + Thread.currentThread().getName());
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.removeLast();
            System.out.println("-----消费者消费了一条数据,有" + list.size() + "条数据   --" + Thread.currentThread().getName());
            list.notifyAll();
        }
    }
}

生产者

public class Producer implements Runnable{
    private final Container mContainer;

    public Producer(Container container) {
        mContainer = container;
    }


    @Override
    public void run() {
        mContainer.product();
    }
}

消费者

public class Consumer implements Runnable {
    private final Container mContainer;

    public Consumer(Container container) {
        mContainer = container;
    }

    @Override
    public void run() {
        mContainer.consume();
    }
}
public static void main(String[] args) {
    Container container = new Container();

    for (int i = 0; i < 8; i++) {
        Producer producer = new Producer(container);
        Thread thread = new Thread(producer);
        thread.setName("生产者线程" + i);
        thread.start();
    }

    for (int i = 0; i < 8; i++) {
        Consumer consumer = new Consumer(container);
        Thread thread = new Thread(consumer);
        thread.setName("消费者线程" + i);
        thread.start();
    }
}

在这里插入图片描述

Container类中的synchronized持有的是list对象锁,那么wait()notify()notifyAll()方法都必须调用list的方法。当然synchrozied也可以持有this,表示当前Container对象锁,或者synchronized修饰在方法上,那么wait()notify()notifyAll()方法都必须调用Container对象的方法,即this.wait()或者wait()

后续文章会有专门关于synchronized的讲解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值