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 = ; //static BlockingQueue<Email> blockingQueue = new LinkedBlockingQueue<Email>(QUEUE_MAX_SIZE); static ArrayBlockingQueue<Email> blockingQueue=new ArrayBlockingQueue<Email>(); /**
* 私有的默认构造子,保证外界无法直接实例化
*/
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();// 两个大小的固定线程池
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,这个大佬写的博客园

最新文章

  1. [LeetCode] Spiral Matrix 螺旋矩阵
  2. Linux磁盘分区及配额
  3. Mina入门实例(一)
  4. Node.js高效按行输出文件内容
  5. python数据结构与算法
  6. Codeforces Round #228 (Div. 2) A. Fox and Number Game
  7. Linux socket 获得本地IP和广播地址
  8. Unity3d碰撞检测中碰撞器与触发器的区别
  9. 如何用pdfbox-app-1.8.10.jar批处理将pdf文档转换成text文档
  10. php测试题整理(0519)
  11. Linux 文件系统同步
  12. 创建Material Design风格Android应用--自定义阴影和裁剪视图
  13. libtask channel机理及调度理解
  14. OpenSSL中的大数接口与基于其的自用RSA加密接口设计
  15. python-web自动化-鼠标操作
  16. 向jsp中引入公共文件
  17. Jmeter(二十七)模拟发送TCP/UDP/HTTP/FTP等请求包(转载)
  18. OI回忆录第一章 逐梦之始
  19. Snmp学习总结(三)——Win7安装和配置SNMP
  20. Umeng社会化组件使用笔记

热门文章

  1. elast数据存放
  2. sql (12) HAVING
  3. CSS——背景渐变
  4. LUOGU P3919 【模板】可持久化数组(主席树)
  5. DNS的解析过程
  6. fiddler设置抓取HTTPS协议数据包
  7. 关于Async与Await的FAQ
  8. (转) Mac下面的SecureCRT(附破解方案) 更新到最新的7.3.7
  9. http://edu.manew.com/ ,蛮牛教育(很少免费),主要是unty3D和大数据方向。适合扫盲
  10. 图解 5 种 Join 连接及实战案例!(inner/ left/ right/ full/ cross)