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锁问题

  • 相关阅读:
    Netty入门
    hashCode方法里为什么选择数字31作为生成hashCode值的乘数
    【转】String hashCode 方法为什么选择数字31作为乘子
    NppFTP小插件的使用
    事务的基础入门
    Code Review 程序员的寄望与哀伤【转载】
    谈谈敏捷开发【转载】
    如何写代码 — 编程内功心法【转载】
    面经【转载】
    Swagger的简单入门【转载】
  • 原文地址:https://www.cnblogs.com/junlinsky/p/13443209.html
Copyright © 2011-2022 走看看