美文网首页
Java并发编程(二):wait() notify() noti

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

作者: CoderCyl | 来源:发表于2020-10-15 21:47 被阅读0次

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

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

    相关文章

      网友评论

          本文标题:Java并发编程(二):wait() notify() noti

          本文链接:https://www.haomeiwen.com/subject/haxapktx.html