• ArrayBlockingQueue的使用案例:


    ArrayBlockingQueue的介绍:

    ArrayBlockingQueue,顾名思义:基于数组的阻塞队列。数组是要指定长度的,所以使用ArrayBlockingQueue时必须指定长度,也就是它是一个有界队列。

    它实现了BlockingQueue接口,有着队列、集合以及阻塞队列的所有方法,

    他有三个构造方法:

    并没有无参构造,所以必须要初始化长度,不让他变成一个无边界的数据队列,可能会存在内存过大的问题

    内部实现了ReentrantLock锁,所以线程是安全的,

    使用场景,异步队列发送邮件:

    首先封装mail对象进queue队列:

    public class Email implements Serializable {
        private static final long serialVersionUID = 1L;
        //必填参数
        private String[] email;//接收方邮件
        private String subject;//主题
        private String content;//邮件内容
        //选填
        private String template;//模板
        private HashMap<String, String> kvMap;// 自定义参数
        
        
        
        public Email() {
            super();
        }
        
        public Email(String[] email, String subject, String content, String template,
                HashMap<String, String> kvMap) {
            super();
            this.email = email;
            this.subject = subject;
            this.content = content;
            this.template = template;
            this.kvMap = kvMap;
        }
    
    
        public String[] getEmail() {
            return email;
        }
        public void setEmail(String[] email) {
            this.email = email;
        }
        public String getSubject() {
            return subject;
        }
        public void setSubject(String subject) {
            this.subject = subject;
        }
        public String getContent() {
            return content;
        }
        public void setContent(String content) {
            this.content = content;
        }
        public String getTemplate() {
            return template;
        }
        public void setTemplate(String template) {
            this.template = template;
        }
        public HashMap<String, String> getKvMap() {
            return kvMap;
        }
        public void setKvMap(HashMap<String, String> kvMap) {
            this.kvMap = kvMap;
        }
    }

    然后写一个MailQueue:

    package com.itstyle.mail.common.queue;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingQueue;
    
    import com.itstyle.mail.common.model.Email;
    /**
    
    public class MailQueue {
         //队列大小
        static final int QUEUE_MAX_SIZE   = 1000;
    
        //static BlockingQueue<Email> blockingQueue = new LinkedBlockingQueue<Email>(QUEUE_MAX_SIZE);
    
        static ArrayBlockingQueue<Email> blockingQueue=new ArrayBlockingQueue<Email>(100);
        
        /**
         * 私有的默认构造子,保证外界无法直接实例化
         */
        private MailQueue(){};
        /**
         * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
         * 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
         */
        private static class SingletonHolder{
            /**
             * 静态初始化器,由JVM来保证线程安全
             */
            private  static MailQueue queue = new MailQueue();
        }
        //单例队列
        public static MailQueue getMailQueue(){
            return SingletonHolder.queue;
        }
        //生产入队
        public  void  produce(Email mail) throws InterruptedException {
            blockingQueue.put(mail);
        }
        //消费出队
        public  Email consume() throws InterruptedException {
            return blockingQueue.take();
        }
        // 获取队列大小
        public int size() {
            return blockingQueue.size();
        }
    }

    里面包括了消费和创建的方法:

     //生产入队
        public  void  produce(Email mail) throws InterruptedException {
            blockingQueue.put(mail);
        }
        //消费出队
        public  Email consume() throws InterruptedException {
            return blockingQueue.take();
        }

    使用静态内部类的方法,保证单利模式

    消费队列:

    package com.itstyle.mail.common.queue;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import com.itstyle.mail.common.model.Email;
    import com.itstyle.mail.service.IMailService;
    
    @Component
    public class ConsumeMailQueue {
        private static final Logger logger = LoggerFactory.getLogger(ConsumeMailQueue.class);
        @Autowired
        IMailService mailService;
        
        @PostConstruct
        public void startThread() {
            ExecutorService e = Executors.newFixedThreadPool(2);// 两个大小的固定线程池
            e.submit(new PollMail(mailService));
            e.submit(new PollMail(mailService));
        }
    
        class PollMail implements Runnable {
            IMailService mailService;
    
            public PollMail(IMailService mailService) {
                this.mailService = mailService;
            }
    
            @Override
            public void run() {
                while (true) {
                    try {
                        Email mail = MailQueue.getMailQueue().consume();
                        if (mail != null) {
                            logger.info("剩余邮件总数:{}",MailQueue.getMailQueue().size());
                            mailService.send(mail);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        @PreDestroy
        public void stopThread() {
            logger.info("destroy");
        }
    }

    这种从线程池获取消费线程来执行,这个里面是一个多线程环境,为什么可以保证线程安全呢,是由于ArrayBlokcingQueue实现了reentranlock来实现的,

     在这里将需要发送邮件的信息添加到队列中去.

    如果需要判断是否满了,就需要使用offer方法,不是使用reminingkey方法:

    可以参看下面文字:https://www.xttblog.com/?p=3686,这个大佬写的博客园

  • 相关阅读:
    数据库时间类型
    【西瓜视频】帮妈妈下载广场舞健身操视频
    Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly缓存、限流、熔断、降级
    Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网关Ocelot+Consul
    Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服务注册,服务发现
    .NET5修改配置不重启自动生效
    RabbitMQ从零到集群高可用.NetCore(.NET5)-高可用集群构建落地
    Redis初步使用记录
    NPM 错误收集及解决方法
    挪动了一个if语句的位置,运行速度大幅提升
  • 原文地址:https://www.cnblogs.com/xiufengchen/p/10863414.html
Copyright © 2020-2023  润新知