zoukankan      html  css  js  c++  java
  • 生产者消费者问题

    生产者消费者问题

    /**
     * 线程之间的通信问题:生产者和消费者问题!  等待唤醒,通知唤醒
     * 线程交替执行  A   B 操作同一个变量   num = 0
     * A num+1
     * B num-1
     */
    public class A {
        public static void main(String[] args) {
            Data data = new Data();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"A").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"B").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"C").start();
    
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"D").start();
        }
    }
    
    // 判断等待,业务,通知
    class Data{ // 数字 资源类
    
        private int number = 0;
    
        //+1
        public synchronized void increment() throws InterruptedException {
            /*
            * 使用while 而不是if的原因:
            * 使用if会存在虚假唤醒的情况。
            * 所谓虚假唤醒是指当前线程被唤醒了,但是if已经执行完了,它不会再次执行,
            * 就不能执行if内的代码即假唤醒。
            */
            while (number!=0){  //0
                // 等待
                this.wait();
            }
            number++;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            // 通知其他线程,我+1完毕了
            this.notifyAll();
        }
    
        //-1
        public synchronized void decrement() throws InterruptedException {
            while (number==0){ // 1
                // 等待
                this.wait();
            }
            number--;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            // 通知其他线程,我-1完毕了
            this.notifyAll();
        }
    
    }
    

    使用JUC解决生产者消费者问题

    在Lock 中由如下描述

    image-20200802173231202

    关于Condition描述如下

    image-20200802173322592

    class BoundedBuffer {
        final Lock lock = new ReentrantLock();
        //用lock.newCondition获得condition
        final Condition notFull  = lock.newCondition(); 
        final Condition notEmpty = lock.newCondition(); 
    
        final Object[] items = new Object[100];
        int putptr, takeptr, count;
    
        public void put(Object x) throws InterruptedException {
            lock.lock(); 
            try {
                while (count == items.length)
                    notFull.await();
                items[putptr] = x;
                if (++putptr == items.length) putptr = 0;
                ++count;
                notEmpty.signal();
            } finally { lock.unlock(); }
        }
    
        public Object take() throws InterruptedException {
            lock.lock(); try {
                while (count == 0)
                    notEmpty.await();
                Object x = items[takeptr];
                if (++takeptr == items.length) takeptr = 0;
                --count;
                notFull.signal();
                return x;
            } finally { lock.unlock(); }
        }
    } 
    

    使用上面的代码实现生产者消费者

    public class B  {
        public static void main(String[] args) {
            Data2 data = new Data2();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"A").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"B").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"C").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"D").start();
    
        }
    }
    
    // 判断等待,业务,通知
    class Data2{ // 数字 资源类
    
        private int number = 0;
    
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        //condition.await(); // 等待
        //condition.signalAll(); // 唤醒全部
        //+1
        public void increment() throws InterruptedException {
            lock.lock();
            try {
                // 业务代码
                while (number!=0){  //0
                    // 等待
                    condition.await();
                }
                number++;
                System.out.println(Thread.currentThread().getName()+"=>"+number);
                // 通知其他线程,我+1完毕了
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
    
        }
    
        //-1
        public synchronized void decrement() throws InterruptedException {
            lock.lock();
            try {
                while (number==0){ // 1
                    // 等待
                    condition.await();
                }
                number--;
                System.out.println(Thread.currentThread().getName()+"=>"+number);
                // 通知其他线程,我-1完毕了
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
    }
    

    运行效果:

    image-20200802174706451

    Condition 精准的通知和唤醒线程

    /**
     * A 执行完调用B,B执行完调用C,C执行完调用A
     */
    public class C {
    
        public static void main(String[] args) {
            Data3 data = new Data3();
    
            new Thread(()->{
                for (int i = 0; i <10 ; i++) {
                    data.printA();
                }
            },"A").start();
    
            new Thread(()->{
                for (int i = 0; i <10 ; i++) {
                    data.printB();
                }
            },"B").start();
    
            new Thread(()->{
                for (int i = 0; i <10 ; i++) {
                    data.printC();
                }
            },"C").start();
        }
    
    }
    
    class Data3{ // 资源类 Lock
    
        private Lock lock = new ReentrantLock();
        private Condition condition1 = lock.newCondition();
        private Condition condition2 = lock.newCondition();
        private Condition condition3 = lock.newCondition();
        private int number = 1; // 1A  2B  3C
    
        public void printA(){
            lock.lock();
            try {
                // 业务,判断-> 执行-> 通知
                while (number!=1){
                    // 等待
                    condition1.await();
                }
                System.out.println(Thread.currentThread().getName()+"=>AAAAAAA");
                // 唤醒,唤醒指定的人,B
                number = 2;
                condition2.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void printB(){
            lock.lock();
            try {
                // 业务,判断-> 执行-> 通知
                while (number!=2){
                    condition2.await();
                }
                System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB");
                // 唤醒,唤醒指定的人,c
                number = 3;
                condition3.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
        public void printC(){
            lock.lock();
            try {
                // 业务,判断-> 执行-> 通知
                // 业务,判断-> 执行-> 通知
                while (number!=3){
                    condition3.await();
                }
                System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB");
                // 唤醒,唤醒指定的人,c
                number = 1;
                condition1.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
    }
    

    image-20200802175136313

    视频参考https://www.bilibili.com/video/BV1B7411L7tE
    上一篇:Lock锁
    下一篇:8锁问题

  • 相关阅读:
    进度条
    html5 表单新增事件
    html5 表单的新增type属性
    html5 表单的新增元素
    html5 语义化标签
    jq 手风琴案例
    codeforces 702D D. Road to Post Office(数学)
    codeforces 702C C. Cellular Network(水题)
    codeforces 702B B. Powers of Two(水题)
    codeforces 702A A. Maximum Increase(水题)
  • 原文地址:https://www.cnblogs.com/junlinsky/p/13443209.html
Copyright © 2011-2022 走看看