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,没有涉及到商品库存),目前用户量还没有上来,目前没有出现问题,但是想到如果用户量变大,下单并发量变大,可能会出现一系列的问题,趁着空闲 ...
随机推荐
- Educational Codeforces Round 61 (Rated for Div. 2)F(区间DP,思维,枚举)
#include<bits/stdc++.h>typedef long long ll;const int inf=0x3f3f3f3f;using namespace std;char ...
- K-Dominant Character (模拟)
You are given a string s consisting of lowercase Latin letters. Character c is called k-dominant iff ...
- 区块链中的密码学(四)- Merkle树和SPV节点
什么是Merkle Tree? Merkle Tree 的命名来自于美国密码学家Ralph C. Merkle ,关于他的个人资料:传送门https://en.wikipedia.org/wiki/R ...
- 13、OpenCV Python canny边缘提取
__author__ = "WSX" import cv2 as cv import numpy as np def lapalian_demo(image): #拉普拉斯算子 # ...
- 使用原生js来操作对象dom的class属性
之前一直都使用jquery来操作dom,今天想自己用原生写一些插件,却发现给dom增删class的时候,使用slice来截取className特别的麻烦,后来发现,原来原生JS本来就有提供api来对d ...
- 20.包含min函数的栈
题目描述: 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 思路分析: 设置两个栈,一个push,一个放置最小元素. 代码: impor ...
- Java基础笔记(十八)——多态
多态表示同一个操作作用在不同对象时,会有不同的结果. 多态可分为编译时多态和运行时多态. 编译时多态:方法重载,编译时就可以确定到底调用哪个方法,可以被看做一个类中的方法多态性. 运行时多态:只有在运 ...
- PANet训练自己的数据(VIA标注)
当前最好的实例分割网络非PANet莫属,可是由于模型太新,网上的资料太少,最近的项目需要 实例分割,只能自己踩踩坑了,目前我还没看到一篇关于PANet训练的博客,只有几篇讲论文的. 环境:ubuntu ...
- spring boot中 启用aspectj
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...
- hdu1686 KMP 求在字符串A中字符串B出现的次数
Oulipo Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...