• 多线程——生产者消费者模式三种实现方式


      生产者消费者模式通过一个阻塞队列来解决两者之间的强耦合问题。阻塞队列相当于一个缓冲区,平衡消费者和生产者的处理能力。

      阻塞队列有数据——生产者不生产,阻塞队列没数据——消费者不消费

    一、synchronized+wait+notifyAll

     生产

    package com.ProductCusromer.method2;
    
    import java.util.List;
    import java.util.Random;
    
    /**
     * @author Millet
     * @date 2020/3/30 17:59
     */
    public class Product2 implements Runnable {
        private List list;
    
        public Product2(List list) {
            this.list = list;
        }
        //多个生产者对应多个消费者
        @Override
        public void run() {
            Random random = new Random(50);//相当于商品
            while (true){
                synchronized (list){
                    while(list.size()>0){
                        //集合中有数据就停止写入,等待消费者消费完
                        try {
                            list.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //执行到这说明集合没有数据了
                    list.add((random.nextInt(50)));
                    //提示
                    System.out.println(Thread.currentThread().getName()+"线程生产了:"+ list.get(0));
                    list.notifyAll();
                }
            }
        }
    }

     消费者

    package com.ProductCusromer.method2;
    
    import java.util.List;
    
    /**
     * @author Millet
     * @date 2020/3/30 18:07
     */
    public class Consumer2 implements Runnable {
        private List list;
    
        public Consumer2(List list) {
            this.list = list;
        }
    
        @Override
        public void run() {
            while(true){
                synchronized (list){
                    while(list.size()<=0){//适合多生产者多消费者
                        try {
                            list.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                     try {
                         Thread.sleep(500);
                      } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
    
                     //提示
                      System.err.println(Thread.currentThread().getName()+"线程消费了:"+ list.remove(0));
                      list.notifyAll();
                    }
                }
        }
    }

    二、ReetrantLock+Condition

    生产者

    package com.ProductCusromer.method3;
    
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    
    /**
     * @author Millet
     * @date 2020/3/30 17:59
     */
    public class Product3 implements Runnable {
        private List list;
        private Lock mLock;
        private Condition mCondition;
        public Product3(List list, Lock lock, Condition condition) {
            this.list = list;
            this.mLock = lock;
            this.mCondition = condition;
        }
        //一个生产者对应一个消费者
        @Override
        public void run() {
            Random random = new Random(50);//相当于商品
            while (true){
                mLock.lock();
                if(list.size()>0){
                    //集合中有数据就停止写入,等待消费者消费完
                    try {
                        mCondition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //执行到这说明集合没有数据了
                list.add((random.nextInt(50)));
                //提示
                System.out.println(Thread.currentThread().getName()+"线程生产了:"+ list.get(0));
                mCondition.signalAll();
                mLock.unlock();
            }
        }
    }

     消费者

    package com.ProductCusromer.method2;
    
    import java.util.List;
    
    /**
     * @author Millet
     * @date 2020/3/30 18:07
     */
    public class Consumer2 implements Runnable {
        private List list;
    
        public Consumer2(List list) {
            this.list = list;
        }
    
        @Override
        public void run() {
            while(true){
                synchronized (list){
                    while(list.size()<=0){//适合多生产者多消费者
                        try {
                            list.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                     try {
                         Thread.sleep(500);
                      } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
    
                     //提示
                      System.err.println(Thread.currentThread().getName()+"线程消费了:"+ list.remove(0));
                      list.notifyAll();
                    }
                }
        }
    }

    三、BlockingQueue实现

    生产者

    package com.ProductCusromer.method3;
    
    import java.util.concurrent.BlockingQueue;
    
    /**
     * @author Millet
     * @date 2020/3/30 21:28
     */
    public class Product4 implements Runnable {
        private BlockingQueue queue;
        private String name;
        public Product4(String name, BlockingQueue queue) {
            this.queue = queue;
            this.name = name;
        }
        @Override
        public void run() {
            while(true){
                try {
                    int val = (int) Math.random();
                    queue.put(val);
                    System.out.println(name + "生产:"+val+".当前队列长度:"+ queue.size());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    消费者

    package com.ProductCusromer.method3;
    
    import java.util.concurrent.BlockingDeque;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    
    /**
     * @author Millet
     * @date 2020/3/30 21:28
     */
    public class Consumer4 implements Runnable{
        private BlockingQueue queue;
        private String name;
        public Consumer4(String name, BlockingQueue queue) {
            this.queue = queue;
            this.name = name;
        }
        @Override
        public void run() {
            try {
                while (true){
                    int val = (int) queue.take();
                    System.out.println(name + "消费:"+val+".当前队列长度:"+ queue.size());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    测试

    package com.ProductCusromer.method3;
    
    import com.ProductCusromer.method1.Consumer1;
    import com.ProductCusromer.method1.Product1;
    
    import javax.persistence.criteria.CriteriaBuilder;
    import java.util.List;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * @author Millet
     * @date 2020/3/30 20:33
     */
    public class Main {
        public static void main(String[] args) {
            BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(20);
            Product4 producer1 = new Product4("生产1号", queue);
            Product4 producer2 = new Product4("生产2号", queue);
            Product4 producer3 = new Product4("生产3号", queue);
    
            Consumer4 consumer1 = new Consumer4("消费1号", queue);
            Consumer4 consumer2 = new Consumer4("消费2号", queue);
    
    // 开始producer线程进行生产
            new Thread(producer1).start();
            new Thread(producer2).start();
            new Thread(producer3).start();
    
    // 开始consumer线程进行消费。
            new Thread(consumer1).start();
            new Thread(consumer2).start();
        }
    }

    结果

  • 相关阅读:
    判断奇偶数2
    判断奇偶数
    15.09.29
    .
    Java代码
    Handler 接收Parcelable ArrayList时返回空的错误
    Android Binder设计与实现
    xml解析代码示例
    解析rss和atom文件出现乱码问题
    使用Html.fromHtml将html格式字符串应用到textview上面
  • 原文地址:https://www.cnblogs.com/qmillet/p/12601518.html
Copyright © 2020-2023  润新知