• 【java线程】生成有限生产,且待消费者消费完全部消息后,生产者消费者相继退出的现实模式


    【代码下载】

    https://files.cnblogs.com/files/heyang78/real_comsumerproducer20220714.rar?t=1657804074

    【书写初衷】

    甚多教程写消费者生产者模式,都是while(true)无限循环,没有一个退出机制,并不符合实际情况。

    为此我书写了一个新模式,让生成有限生产,且待消费者消费完全部消息后,生产者消费者相继退出。

    这种模式比较适合有限数据的场合。

    生产者最后给消费者发确定的离开消息是关键一步。

    【代码】

    队列类: 

    package com.hy.lab.comsumerproducer;
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    
    public class Queue<T>{
        private BlockingQueue<T> queue;
    
        private int limit;
    
        public Queue(int limit){
            this.limit=limit;
            queue=new ArrayBlockingQueue<>(limit);
        }
    
        public synchronized void put(T data) throws InterruptedException{
            while(queue.size()==limit){ // 此处while/if皆可
                wait();
            }
    
            queue.add(data);
            this.notifyAll();
        }
    
        public synchronized T take() throws InterruptedException{
            while(queue.isEmpty()){ // 此处while/if皆可
                wait();
            }
    
            T data=queue.poll();
            this.notifyAll();
    
            return data;
        }
    
        public void tellComsumerLeave(){
            //this.notify();
        }
    }

    生产者类:

    package com.hy.lab.comsumerproducer;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.TimeUnit;
    
    public class Producer extends Thread{
        Queue<String> queue;
        int msgCnt;
        CountDownLatch cdl;
    
        public Producer(Queue<String> queue,int msgCnt,CountDownLatch cdl){
            this.queue=queue;
            this.msgCnt=msgCnt;
            this.cdl=cdl;
        }
    
        public void run(){
            try {
                int i = 0;
                while (i < msgCnt) {
                    String msg="消息:" + i + ".";
                    System.out.println("生产者制成"+msg);
                    queue.put(msg);
                    i++;
                }
    
                cdl.await(10, TimeUnit.SECONDS);
                queue.put("LEAVE");// 最后发一个确定的标志离开的消息将wait的comsumer解救出来
                System.out.println("生产者退出");
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
    }

    消费者类:

    package com.hy.lab.comsumerproducer;
    
    import java.util.concurrent.CountDownLatch;
    
    public class Comsumer extends Thread{
        Queue<String> queue;
        Producer producer;
        CountDownLatch cdl;
    
        public Comsumer(Queue<String> queue,Producer producer,CountDownLatch cdl){
            this.queue=queue;
            this.producer=producer;
            this.cdl=cdl;
        }
    
        public void run(){
            try {
                while (true) {
                    String msg=queue.take();
                    if(msg.equalsIgnoreCase("LEAVE")==false) {
                        System.out.println("   消费者取得" + msg);
                        cdl.countDown();
                    }else{
                        break;
                    }
                }
    
                System.out.println("   消费者离开");
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
    }

    测试类: 

    package com.hy.lab.comsumerproducer;
    
    import java.util.concurrent.CountDownLatch;
    
    public class Test {
        public static void main(String[] args){
            Queue<String> queue=new Queue<>(5);
    
            final int msgCnt=10;
            CountDownLatch cdl=new CountDownLatch(msgCnt);
    
            Producer producer=new Producer(queue,msgCnt,cdl);
            producer.start();
    
            Comsumer comsumer=new Comsumer(queue,producer,cdl);
            comsumer.start();
        }
    }

    【输出】

    生产者制成消息:0.
    生产者制成消息:1.
    生产者制成消息:2.
    生产者制成消息:3.
    生产者制成消息:4.
    生产者制成消息:5.
    生产者制成消息:6.
       消费者取得消息:0.
    生产者制成消息:7.
       消费者取得消息:1.
    生产者制成消息:8.
       消费者取得消息:2.
       消费者取得消息:3.
    生产者制成消息:9.
       消费者取得消息:4.
       消费者取得消息:5.
       消费者取得消息:6.
       消费者取得消息:7.
       消费者取得消息:8.
       消费者取得消息:9.
    生产者退出
       消费者离开
    
    Process finished with exit code 0
    缩进使得消费者代码和生产者代码输出更清晰。

     【参考资料】

    《Java编程的逻辑》马俊昌著 机械工业出版社出版 P453页

    原例子是基于生产者消费者无限循环,缺乏退出机制。本人已经让原作升华了。

    END

  • 相关阅读:
    dfssvc.exe
    我左边的公告
    再做了一个LOGO
    做一个调查,请大家帮忙
    如果年三十没有人陪我
    我喜欢这个模版
    cisvc.exe是什么服务
    IIS与SQL服务器安全加固
    终于申请到了blogs
    重发LOGO
  • 原文地址:https://www.cnblogs.com/heyang78/p/16479136.html
Copyright © 2020-2023  润新知