ArrayBlockingQueue的使用案例:
2024-10-07 22:51:44
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,这个大佬写的博客园
最新文章
- [LeetCode] Spiral Matrix 螺旋矩阵
- Linux磁盘分区及配额
- Mina入门实例(一)
- Node.js高效按行输出文件内容
- python数据结构与算法
- Codeforces Round #228 (Div. 2) A. Fox and Number Game
- Linux socket 获得本地IP和广播地址
- Unity3d碰撞检测中碰撞器与触发器的区别
- 如何用pdfbox-app-1.8.10.jar批处理将pdf文档转换成text文档
- php测试题整理(0519)
- Linux 文件系统同步
- 创建Material Design风格Android应用--自定义阴影和裁剪视图
- libtask channel机理及调度理解
- OpenSSL中的大数接口与基于其的自用RSA加密接口设计
- python-web自动化-鼠标操作
- 向jsp中引入公共文件
- Jmeter(二十七)模拟发送TCP/UDP/HTTP/FTP等请求包(转载)
- OI回忆录第一章 逐梦之始
- Snmp学习总结(三)——Win7安装和配置SNMP
- Umeng社会化组件使用笔记
热门文章
- elast数据存放
- sql (12) HAVING
- CSS——背景渐变
- LUOGU P3919 【模板】可持久化数组(主席树)
- DNS的解析过程
- fiddler设置抓取HTTPS协议数据包
- 关于Async与Await的FAQ
- (转) Mac下面的SecureCRT(附破解方案) 更新到最新的7.3.7
- http://edu.manew.com/ ,蛮牛教育(很少免费),主要是unty3D和大数据方向。适合扫盲
- 图解 5 种 Join 连接及实战案例!(inner/ left/ right/ full/ cross)