基于springboot实现轮询线程自动执行任务

本文使用:
Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,
但不能在指定时间运行。一般用的较少。
类似于quartz任务调度:demo地址 lsr-core-base模块中
直接上代码:
线程基类:
package cn.lsr.core.thread; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.sql.Timestamp;
import java.util.Timer;
import java.util.TimerTask; /**
* @Description: 轮询线程基类
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
public abstract class AbstractPollThread {
private static final Logger log = LoggerFactory.getLogger(AbstractPollThread.class);
private long delay = 60; // 延期时间(第一次执行时间-调用时间)
private long timeInterval = 60; //时间间隔(s)
private Timer timer;
private Timestamp lastProcess = null; //上次执行的时间
private boolean isTimerStart = false; //定时器是否启动
private boolean isOnProcessing = false; //是否在执行处理
private final String threadName; //线程名称
private final String threadId; //线程标识
private final String longname; //中文名称
private long processCount = 0; //执行次数
private long processTime = 0; //已运行时间
private long errorProcessCount = 0; //执行失败的次数 public AbstractPollThread(String threadId, String threadName, String longname, Long delay, Long timeInterval) {
this.threadId = threadId;
this.threadName = threadName;
this.longname = longname;
if (timeInterval != null && timeInterval > 0)
this.timeInterval = timeInterval; if (delay != null)
this.delay = delay;
PollThreadManager.get().register(threadName, this);
}
/**
* 线程启动时回调方法。
*/
public void init() { } /**
* 轮询间隔回调方法。
*/
public abstract void process(); /**
* 启动方法
*/
public void startup() {
this.timer = new Timer( "lsr-timer-" + this.threadName, false);
try {
this.timer.schedule(new TimerTask() {
boolean initialized = false;
@Override
public void run() {
// 异步线程资源清理
//清理完上下文数据,在打log4j标记
log.info("--------------------轮训线程[" + AbstractPollThread.this.threadName + "]开始调度--------------------");
// 2015.4.20 每个线程开始受理请求时对数据库连接进行检查,若不可用则重连一次
long start = System.currentTimeMillis();
try {
AbstractPollThread.this.isOnProcessing = true;
AbstractPollThread.this.lastProcess = new Timestamp(System.currentTimeMillis());
AbstractPollThread.this.process();
AbstractPollThread.this.isOnProcessing = false;
}
catch (Throwable t) {
log.error("轮询线程出现异常", t);
AbstractPollThread.this.errorProcessCount++;
} finally {
AbstractPollThread.this.processCount++;
AbstractPollThread.this.processTime = AbstractPollThread.this.processTime + System.currentTimeMillis() - start;
log.info("--------------------轮训线程[" + AbstractPollThread.this.threadName + "]调度结束. [" + (System.currentTimeMillis() - start) + "]--------------------");
// 异步线程资源清理
}
}
}, this.delay * 1000, this.timeInterval * 1000);
this.isTimerStart = true;
} catch (Exception e) {
this.isTimerStart = false;
log.error("轮询线程设置定时器失败,", e);
throw new RuntimeException("轮询线程设置定时器失败", e);
}
} public void shutdown() {
try {
if (this.timer != null)
this.timer.cancel();
this.isTimerStart = false;
} catch (Exception e) {
this.isTimerStart = false;
log.error("关闭轮询线程中的定时器失败", e);
throw new RuntimeException("关闭轮询线程中的定时器失败", e);
}
} public String getThreadName() {
return this.threadName;
} public String getLongname() {
return this.longname;
} public long getProcessCount() {
return this.processCount;
} public long getProcessTime() {
return this.processTime;
} public long getErrorProcessCount() {
return this.errorProcessCount;
} public void setTimeInterval(long timeInterval) {
this.timeInterval = timeInterval;
} public long getTimeInterval() {
return this.timeInterval;
} public boolean isTimerStart() {
return this.isTimerStart;
} public boolean isOnProcessing() {
return this.isOnProcessing;
} public String getLastProcessTime() {
return this.lastProcess == null ? null : this.lastProcess.toString();
} public void resetCountInfo() {
this.processCount = 0;
this.processTime = 0;
this.errorProcessCount = 0;
this.lastProcess = null;
} }
轮询线程配置类:
package cn.lsr.core.thread; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; /**
* @Description: 轮询线程配置
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
public class PollThreadConfig {
/**
* 轮询线程ID
*/
private String threadId; /**
* 轮询线程名称
*/
private String threadName; /**
* 间隔时间
*/
private Long timeInterval; /**
* 轮询线程首次延迟时间
*/
private Long delay; // get set 省略 }
线程管理器:
package cn.lsr.core.thread; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; /**
* @Description: 线程管理器
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
public class PollThreadManager {
private final static Map<String, AbstractPollThread> pollThreadMap = new ConcurrentHashMap<String, AbstractPollThread>(); private final static PollThreadManager instance = new PollThreadManager(); public static PollThreadManager get() {
return instance;
} public void register(String threadName, AbstractPollThread pollThread) {
pollThreadMap.put(threadName, pollThread);
} public AbstractPollThread getPollThread(String threadName) {
return pollThreadMap.get(threadName);
} public Map<String, AbstractPollThread> getPollThreads() {
return pollThreadMap;
}
}
测试线程(可扩展):
package cn.lsr.core.thread; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.sql.Timestamp; /**
* @Description: 测试轮询线程
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
public class TestServerPollThread extends AbstractPollThread{
private static final Logger log = LoggerFactory.getLogger(TestServerPollThread.class);
/**
* 插件 - OnlineServerManagerPlugin -启动的时候初始化线程
* @param threadId 轮询线程ID
* @param threadName 轮询线程名称
* @param longname 中文名称
* @param delay 轮询线程首次延迟时间
* @param timeInterval 时间间隔
*/
public TestServerPollThread(String threadId, String threadName, String longname, Long delay, Long timeInterval) {
super(threadId, threadName, longname, delay, timeInterval);
} /**
* 轮询间隔回调方法
*/
@Override
public void process() {
log.info("刷新时间为:{}", new Timestamp(System.currentTimeMillis()));
//逻辑
}
}
使用:
//注入:
private TestServerPollThread testServerPollThread;
// 封装的工具类,获取的ioc的线程配置
PollThreadConfig pollThreadConfig = SpringUtil.getBean(PollThreadConfig.class);
testServerPollThread = new TestServerPollThread(pollThreadConfig.getThreadId(),pollThreadConfig.getThreadName(),pollThreadConfig.getThreadName(),pollThreadConfig.getDelay(),pollThreadConfig.getTimeInterval());
//调用方法
testServerPollThread.startup();
application.properties:
##################################### 轮询线程 #######################################
#开关
lsr.poll.thread.enabled=true
#线程id
lsr.poll.thread.threadId=LSRThread
#线程中文名
lsr.poll.thread.threadName=轮询线程
#间隔时间
lsr.poll.thread.timeInterval=60
#加载延迟时间
lsr.poll.thread.delay=60
基于springboot实现轮询线程自动执行任务的更多相关文章
- java用while循环设计轮询线程的性能问题
java用while循环设计轮询线程的性能问题 轮询线程在开发过程中的应用是比较广泛的,在这我模拟一个场景,有一个队列和轮询线程,主线程往队列中入队消息,轮询线程循环从队列中读取消息并打印消息内容.有 ...
- Ajax轮询消息自动提示(消息盒子)
经过一下午写了个消息盒子的例子,用的是ajax方式轮询读取,没有用到后台自动“推”数据的方式,效果良好. <%@ Page Language="C#" AutoEventWi ...
- springBoot启动时让方法自动执行的几种实现方式
一.开篇名义 在springBoot中我们有时候需要让项目在启动时提前加载相应的数据或者执行某个方法,那么实现提前加载的方式有哪些呢?接下来我带领大家逐个解答 1.实现ServletContextAw ...
- 使用Azure Functions 在web 应用中启用自动更新(一)分析基于轮询的 Web 应用的限制
1,引言 上一篇介绍了使用使用 Visual Studio 开发 "Azure Functions" 函数,此篇介绍 “Azure Functions” 的测试以及直接从 Vist ...
- 如何从线程返回信息——轮询、回调、Callable
考虑有这样一个LiftOff类: /** * 类LiftOff.java的实现描述:显示发射之前的倒计时 * * @author wql 2016年9月21日 下午1:46:46 */ public ...
- 负载均衡算法: 简单轮询算法, 平滑加权轮询, 一致性hash算法, 随机轮询, 加权随机轮询, 最小活跃数算法(基于dubbo) java代码实现
直接上干活 /** * @version 1.0.0 * @@menu <p> * @date 2020/11/17 16:28 */ public class LoadBlance { ...
- Apollo 3 定时/长轮询拉取配置的设计
前言 如上图所示,Apollo portal 更新配置后,进行轮询的客户端获取更新通知,然后再调用接口获取最新配置.不仅仅只有轮询,还有定时更新(默认 5 分钟一次).目的就是让客户端能够稳定的获取到 ...
- node.js中的事件轮询Event Loop
任务队列/事件队列 "任务队列"是一个事件的队列,IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈" ...
- squid日志配置与轮询
squid日志分类及参数 SQUID默认的log文件非常多,其中最重要的LOG日志有三个,分别为access.log.store.log.cache.log.三个日志的记录的内容如下: access. ...
随机推荐
- 自己动手系列----使用数组实现一个简单的Set
Set:注重独一无二的性质,该体系集合可以知道某物是否已近存在于集合中,不会存储重复的元素用于存储无序(存入和取出的顺序不一定相同)元素,值不能重复.主要有HashSet和TreeSet两大实现类. ...
- POJ2456 Aggressive cows(二分)
链接:http://poj.org/problem?id=2456 题意:一个数轴上n个点,每个点一个整数值,有c个奶牛,要放在这些点的某几个上,求怎么放可以使任意两个奶牛间距离的最小值最大,求这个最 ...
- Linux - Deepin Linux,intel无线网卡下载慢、不能跑满宽带的解决方案
解决方案 将 /etc/modprobe.d/iwlwifi.conf中的11n_disable=1删掉,重启. 参考 https://bbs.deepin.org/forum.php?mod=vie ...
- IntelliJ IDEA 2017.3尚硅谷-----配置 Maven
- Java-POJ1005-I Think I Need a Houseboat
盗用的翻译,哈哈哈!白嫖就完事了. 题目: 密西西比河岸某处陆地因为河水侵蚀,每年陆地面积都在减少,每年减少50平方英里,减少的陆地面积呈半圆形,即该半圆形面积以每年50平方英里的速度增长.在第一年初 ...
- Junit +cucumber 运行报错 initiallizationError
step1: 访问 https://search.maven.org/ 搜索下载相关jar包 step2: 访问 http://maven.outofmemory.cn/info.cukes/cuc ...
- NOIP做题练习(day4)
A - 同花顺 题面 题解 30分做法 爆搜即可. 60分做法 去重+贪心. 100分做法 去重+贪心后,我们要寻找一段符合条件的最长同花上升子序列 \(L\),\(n-L\) 即为所求的答案. 首先 ...
- 题解 【洛谷P4290】 [HAOI2008]玩具取名
这道题很明显是区间DP. 为了方便表示,我们可以将'W'.'I'.'N'.'G'分别设为1.2.3.4. 另外,DP可能有点丑,记忆化搜索可能写起来更容易理解. AC代码: #include < ...
- 【转载】C++面试题(51-100)
转自:http://www.jobui.com/mianshiti/it/cpp/5018/ 51. 引用与指针有什么区别? 答 .1) 引用必须被初始化,指针不必. 2) 引用初始化以后不能被改变 ...
- poj 2195 Going Home(最小费用流)
题目链接:http://poj.org/problem?id=2195 题目大意是给一张网格,网格中m代表人,h代表房子,网格中的房子和人数量相等,人可以向上向下走,每走1步花费加1,每个房子只能住一 ...