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,没有涉及到商品库存),目前用户量还没有上来,目前没有出现问题,但是想到如果用户量变大,下单并发量变大,可能会出现一系列的问题,趁着空闲 ...
随机推荐
- 787. Cheapest Flights Within K Stops
There are n cities connected by m flights. Each fight starts from city u and arrives at v with a pri ...
- loj#6363. 「地底蔷薇」(拉格朗日反演+多项式全家桶)
题面 传送门 题解 肝了一个下午--我老是忘了拉格朗日反演计算的时候多项式要除以一个\(x\)--结果看它推倒简直一脸懵逼-- 做这题首先你得知道拉格朗日反演是个什么东西->这里 请坐稳,接下来 ...
- bzoj3328: PYXFIB(单位根反演+矩阵快速幂)
题面 传送门 题解 我们设\(A=\begin{bmatrix}1 & 1 \\ 1 & 0\end{bmatrix}\),那么\(A^n\)的左上角就是\(F\)的第\(n\)项 所 ...
- Hystrix线程隔离技术解析-线程池(转)
认识Hystrix Hystrix是Netflix开源的一款容错框架,包含常用的容错方法:线程隔离.信号量隔离.降级策略.熔断技术. 在高并发访问下,系统所依赖的服务的稳定性对系统的影响非常大,依赖有 ...
- 牛客国庆集训day5 G 贵族用户 (模拟)
链接:https://www.nowcoder.com/acm/contest/205/G来源:牛客网 题目描述 终于活成了自己讨厌的样子. 充钱能让你变得更强. 在暖婊这个游戏里面,如果你充了x元钱 ...
- Palindromes _easy version(reverse)
Problem Description “回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串.请写一个程序判断读入的字符串是否是“回文”. Input 输入包 ...
- Codeforces Round #529 (Div. 3) C. Powers Of Two
http://codeforces.com/contest/1095/problem/C 题意:给n找出k个2的幂,加起来正好等于n.例如 9,4:9 = 1 + 2 + 2 + 4 思路:首先任何数 ...
- hau 1870 愚人节的礼物(栈)
愚人节的礼物 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- python3 enumerate()函数笔记
d={"A":"a","B":"b","C":"c","D" ...
- 使用vlookup函数下拉全部相同解决
菜单“公式”-“计算选项”改为自动 ref: https://zhidao.baidu.com/question/561971299094821004.html