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,这个大佬写的博客园

ArrayBlockingQueue的使用案例:的更多相关文章

  1. 29、java中阻塞队列

    阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞.试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列 ...

  2. Java多线程系列十——BlockingQueue

    参考资料:http://ifeve.com/java-synchronousqueue/http://www.cnblogs.com/jackyuj/archive/2010/11/24/188655 ...

  3. java 5并发中的阻塞队列ArrayBlockingQueue的使用以及案例实现

    演示一个阻塞队列的使用 public class BlockingQueueTest { public static void main(String[] args) { //创建一个包含三个元素的阻 ...

  4. ArrayBlockingQueue 阻塞队列 生产者 与消费者案例

    package com.originalityTest; import java.net.UnknownHostException; import java.util.ArrayList; impor ...

  5. 线程高级应用-心得7-java5线程并发库中阻塞队列Condition的应用及案例分析

    1.阻塞队列知识点 阻塞队列重要的有以下几个方法,具体用法可以参考帮助文档:区别说的很清楚,第一个种方法不阻塞直接抛异常:第二种方法是boolean型的,阻塞返回flase:第三种方法直接阻塞. 2. ...

  6. SpringBoot开发案例从0到1构建分布式秒杀系统

    前言 ​最近,被推送了不少秒杀架构的文章,忙里偷闲自己也总结了一下互联网平台秒杀架构设计,当然也借鉴了不少同学的思路.俗话说,脱离案例讲架构都是耍流氓,最终使用SpringBoot模拟实现了部分秒杀场 ...

  7. 并发编程(八)—— Java 并发队列 BlockingQueue 实现之 ArrayBlockingQueue 源码分析

    开篇先介绍下 BlockingQueue 这个接口的规则,后面再看其实现. 阻塞队列概要 阻塞队列与我们平常接触的普通队列(LinkedList或ArrayList等)的最大不同点,在于阻塞队列的阻塞 ...

  8. redis系列:通过日志案例学习string命令

    前言 该文章将通过一个小demo将讲述Redis中的string类型命令.demo将以springboot为后台框架快速开发,iview前端框架进行简单的页面设计,为了方便就不使用DB存储数据了,直接 ...

  9. ArrayBlockingQueue使用

    阻塞与非阻塞: 阻塞: 阻塞调用是没有获得资源则挂起进程,被挂起的进程进入休眠状态,调用的函数只有在得到结果之后才返回,进程继续. 对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性,但并不是一一 ...

随机推荐

  1. 【转载】C# 开源库大全非常好

    原文地址:http://m.blog.csdn.net/woddle/article/details/37311877 C#开源大全 商业协作和项目管理平台-TeamLab 网络视频会议软件-VMuk ...

  2. shell命令 安装软件包

    软件包分类 Debian Linux首先提出  “软件包”   的管理机制——Deb软件包 Redhat Linux基于这个理念推出了自己的软件包管理机制——Rpm软件包 安装包格式: filenam ...

  3. vc面试题目

    class B { public: B() { cout << "default constructor" << endl; } ~B() { cout & ...

  4. 蛮好用的Gungho重点工作督查督办跟踪管理系统

    重点工作督查督办跟踪管理系统可以实现: 为了确保上级重要决定.指示和本单位重大目标和工作部署及时落到实处,确定实效,提升办事效率. 重点工作督查督办事项包括: 1)上级单位或领导的批示指示: 2)公司 ...

  5. [转]nginx简易教程

    安装 nginx官网下载地址 发布版本分为 Linux 和 windows 版本. 也可以下载源码,编译后运行. 从源代码编译 Nginx 把源码解压缩之后,在终端里运行如下命令: $ ./confi ...

  6. LCD Common电压

    因为驱动液晶翻转靠的是两个玻璃电极上的电压差,而电压差是由电容提供的,电容一端接到S基,另一端接到一个基准电压上,这个电压就是Common电压.

  7. react 实现类似vue中的<keep-alive>的功能,并解决antd-mobile切换回来时的空白

    在移动端的spa页面中,只要使用到了路由就很有必要使用到状态保存的功能,这样才能保证在页面进行切换的时候,让用户可以看到刚才滑动的地方,让用户的体验更加友好.这儿我找到了react-router-ca ...

  8. 0916CSP-S模拟测试赛后总结

    40分-rank35. 不想找借口.实力不行. 赛时状态没出什么大问题.就是实力太弱了. 天皇又AK了.去问了一下,他说全是简单题…… 后来发现一些人用非正解AC了. 但是天皇题题正解题题首切啊. 还 ...

  9. Windows下DNS ID欺骗的原理与实现

    域名系统(DNS)是一种用于TCP/IP应用程序的分布式数据库,它提供主机名字和IP地址之间的转换信息.通常,网络用户通过UDP协议和DNS服务器进行通信,而服务器在特定的53端口监听,并返回用户所需 ...

  10. 如何将制定目录加入到PYTHONPATH

    1 问题背景 TensorFlow Object Detection API 是以Slim为基础实现的,需要将Slim的目录加入PYTHONPATH后才能正确运行. 2 机器环境 window10 a ...