java 使用Queue在队列中异步执行任务
先创建一个总的Handler(队列统一处理接口),名字就叫做 QueueTaskHandler
public interface QueueTaskHandler { void processData();
}
然后写一个队列服务类,就不多做说明了,我的注释已经写的很清楚了
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue; @Component
public class QueueGenerationService{ // 日志监控
private static final Logger log = LoggerFactory.getLogger(QueueGenerationService.class);
// 根据业务与服务器性能自行配置 这里我配置的是最多50000个任务
// LinkedBlockingQueue构造的时候若没有指定大小,则默认大小为Integer.MAX_VALUE
private final LinkedBlockingQueue<QueueTaskHandler> tasks = new LinkedBlockingQueue<QueueTaskHandler>(50000);
// 类似于一个线程总管 保证所有的任务都在队列之中
private ExecutorService service = Executors.newSingleThreadExecutor();
// 检查服务是否运行
private volatile boolean running = true;
//线程状态
private Future<?> serviceThreadStatus = null; @PostConstruct
public void init() {
serviceThreadStatus = service.submit(new Thread(new Runnable() {
@Override
public void run() {
while (running) {
try {
//开始一个任务
QueueTaskHandler task = tasks.take();
try {
task.processData();
} catch (Exception e) {
log.error("任务处理发生错误", e);
}
} catch (InterruptedException e) {
log.error("服务停止,退出", e);
running = false;
}
}
}
}, "save data thread"));
} public boolean addData(QueueTaskHandler dataHandler) {
if (!running) {
log.warn("service is stop");
return false;
}
//offer 队列已经满了,无法再加入的情况下
boolean success = tasks.offer(dataHandler);
if (!success) {
log.warn("添加任务到队列失败");
}
return success;
}
//判断队列是否有任务
public boolean isEmpty() {
return tasks.isEmpty();
}
public boolean checkServiceRun() {
return running && !service.isShutdown() && !serviceThreadStatus.isDone();
} public void activeService() {
running = true;
if (service.isShutdown()) {
service = Executors.newSingleThreadExecutor();
init();
log.info("线程池关闭,重新初始化线程池及任务");
}
if (serviceThreadStatus.isDone()) {
init();
log.info("线程池任务结束,重新初始化任务");
}
} @PreDestroy
public void destory() {
running = false;
service.shutdownNow();
}
}
接下来就可以开始写你的业务Handler了
public class TestServiceHandler implements QueueTaskHandler { // ******* start 这一段并不是必要的,这是示范一个传值的方式
private String name; private Integer age; public TestServiceHandler(String name) {
this.name = name;
} public TestServiceHandler(Integer age) {
this.age = age;
} public TestServiceHandler(String name, Integer age) {
this.name = name;
this.age = age;
} // ****** end // 这里也就是我们实现QueueTaskHandler的处理接口
@Override
public void processData() {
// 可以去做你想做的业务了
// 这里需要引用spring的service的话,我写了一个工具类,下面会贴出来
// ItestService testService = SpringUtils.getBean(ItestService.class);
System.out.println("name > " + name + "," + "age > " + age);
} }
那么我们来在service中添加一个任务
// 这里注入队列服务
@Autowired
private QueueGenerationService queueGenerationService;
// 在方法中调用与传参的方式
queueGenerationService.addData(new TestServiceHandler("小明",5));
整个过程就结束了,然后在你的业务Handler中如果需要使用其他的bean比如service,那么请试试我写的这个工具类
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; @Component
public class SpringUtils implements ApplicationContextAware { private static ApplicationContext applicationContext; /**
* @return
* @Description 获取applicationContext
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
} @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtils.applicationContext == null) {
SpringUtils.applicationContext = applicationContext;
}
} /**
* @param name
* @return
* @Description 通过name获取 Bean.
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
} /**
* @param clazz
* @return
* @Description 通过class获取Bean.
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
} /**
* @param name
* @param clazz
* @return
* @Description 通过name, 以及Clazz返回指定的Bean
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
} }
如果大家有什么不解,或意见,欢迎在下方留言,楼主看到就会回复的,谢谢。
java 使用Queue在队列中异步执行任务的更多相关文章
- Java的栈和队列
package com.ipmotor.sm.db;import java.util.LinkedList;import java.util.Queue;import java.util.Stack; ...
- java中使用队列:java.util.Queue (转)
Queue接口与List.Set同一级别,都是继承了Collection接口.LinkedList实现了Queue接 口.Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类 ...
- Java中的队列:java.util.Queue接口
队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作. Queue接口与List.Set同一级别,都是继承了Collection接口.Linked ...
- java中使用队列:java.util.Queue
在java5中新添加了java.util.Queue接口,用以支持队列的常见操作.该接口扩展了java.util.Collection接口.Queue使用时要尽量避免Collection的add()和 ...
- java中使用队列:java.util.Queue(转)
队列是一种特殊的线性表,是运算受到限制的一种线性表,只允许在表的一端进行插入,而在另一端进行删除元素的线性表.队尾(rear)是允许插入的一端.队头(front)是允许删除的一端.空队列是不含元素的空 ...
- Java分布式:消息队列(Message Queue)
Java分布式:消息队列(Message Queue) 引入消息队列 消息,是服务间通信的一种数据单位,消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象.队列,是一种常见的数据结 ...
- django-celery 创建多个broker队列 异步执行任务时指定队列
一.这里不再详细述说 django 框架中如何使用celery, 重点放在如何实现创建多个队列, 并指定队列存放异步任务 笔者使用 django-celery==3.2.2 模块, 配置项及配置参 ...
- 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)
首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...
- SpringBoot项目框架下ThreadPoolExecutor线程池+Queue缓冲队列实现高并发中进行下单业务
主要是自己在项目中(中小型项目) 有支付下单业务(只是办理VIP,没有涉及到商品库存),目前用户量还没有上来,目前没有出现问题,但是想到如果用户量变大,下单并发量变大,可能会出现一系列的问题,趁着空闲 ...
随机推荐
- I - 一次元リバーシ / 1D Reversi(水题)
Problem Statement Two foxes Jiro and Saburo are playing a game called 1D Reversi. This game is playe ...
- 我的iphone不能被虚拟机识别怎么办
我的iphone不能被虚拟机识别怎么办 听语音 | 浏览:3890 | 更新:2015-11-04 15:28 | 标签:iphone vmware ios 1 2 3 4 5 6 分步阅读 特大喜讯 ...
- maven+selenium+java+testng+jenkins自动化测试
最近在公司搭建了一套基于maven+selenium+java+testng+jenkins的自动化测试框架,免得以后重写记录下 工程目录 pom.xml <project xmlns=&quo ...
- 调停者模式Mediator(中介者模式)详解
原文链接:https://www.cnblogs.com/java-my-life/archive/2012/06/20/2554024.html 在阎宏博士的<JAVA与模式>一书中开头 ...
- BA 的职责
Responsibility: 确定系统应用范围:获取实际业务情况(但是并不包含与用户完善实际业务的过程),与用户一起分析实际业务中需要通过软件应用来完成的部分: 备注:是否要与用户一同来分析软件应用 ...
- 对状压dp的见解
看了好几篇博客,终于对一些简单的状压dp有了点了解.就像HDU1074. 有个博客:https://blog.csdn.net/bentutut/article/details/70147989 感觉 ...
- error : Could not load UI satellite dll 'TrackerUI.dll'. Make sure it exists in an LCID subdirectory of 'C:\Program Files (x86)\MSBuild\12.0\bin\'.
原因 VS2013 + QT环境部署好后, 又安装了VS2015\ 解决方案: 在另一台电脑里重装VS2013, 并将 C:\Program Files (x86)\MSBuild\12.0\B ...
- 【笔记】MySQL学习之索引
[笔记]MySQL学习之索引 一 索引简单介绍 索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构.类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可. 普通 ...
- css过渡transition
定义 过渡transition是一个复合属性,包括transition-property.transition-duration.transition-timing-function.transiti ...
- slf4j + loback配置
目前Java主流的log体系是 Slf4j +logback Spring boot 中配置log十分简单,常见的方式在application.yml文件中使用如下配置 logging: path: ...