java环形队列_环形队列高效触发大量超时任务的算法实现
发布日期:2022-02-03 15:25:00 浏览次数:5 分类:技术文章

本文共 5065 字,大约阅读时间需要 16 分钟。

基于环形队列的超时触发算法只需要一个timer即可实现批量超时任务的触发,CPU消耗低,效率高。原理介绍,下面是此算法的简单实现。

1,TaskHolder.javapackage com.zws.timer;

/**

*

* @author wensh.zhu

* @date 2018-04-22

*/

public class TaskHolder {

/** 任务所需等待的圈数,即任务需要走几圈**/

private int cycles;

private int delays;

private Runnable task;

public TaskHolder() {}

public TaskHolder(int cycles, int delays, Runnable task) {

this.cycles = cycles;

this.delays = delays;

this.task = task;

}

public boolean isTimeOut() {

return cycles <= 0;

}

public void cutDown() {

cycles --;

}

public int getCycles() {

return cycles;

}

public void setCycles(int cycles) {

this.cycles = cycles;

}

public int getDelays() {

return delays;

}

public void setDelays(int delays) {

this.delays = delays;

}

public Runnable getTask() {

return task;

}

public void setTask(Runnable task) {

this.task = task;

}

@Override

public String toString() {

return "TaskHolder[cycles=" + cycles + ", delays=" + delays + "]";

}

}

2,TimerContext.javapackage com.zws.timer;

import java.util.Map;

import java.util.Queue;

import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.ConcurrentLinkedQueue;

/**

*

* @author wensh.zhu

* @date 2018-04-22

*/

public class TimerContext {

public static final int DEFAULT_TICKS = 60;

public static final int DEFAULT_TICK_DURATION = 1;

private Map> taskHolders;

private volatile int currentTick = 0;

/** tick一圈的长度 **/

private int ticks = DEFAULT_TICKS;

/** 每tick一次的时间间隔,单位:秒**/

private int tickDuration = DEFAULT_TICK_DURATION;

public TimerContext() {

init();

}

public TimerContext(int ticks, int tickDuration) {

if (ticks <= 0)

throw new IllegalArgumentException("ticks must be greater than 0");

if (tickDuration <= 0)

throw new IllegalArgumentException("tickDuration must be greater than 0");

this.ticks = ticks;

this.tickDuration = tickDuration;

init();

}

private void init() {

taskHolders = new ConcurrentHashMap>();

for (int i = 0; i 

taskHolders.put(i, new ConcurrentLinkedQueue());

}

/**

* 添加一个定时任务并计算需要走的圈数和落脚的index

* @param task

* @param delays

*/

public void addTask(Runnable task, int delays) {

if (task == null)

throw new NullPointerException("task must not be null");

if (delays <=0)

throw new IllegalArgumentException("delays must be greater than 0");

int allSeconds = ticks * tickDuration;

int cycles = delays / allSeconds;

int index = ((delays % allSeconds) / tickDuration) + currentTick;

TaskHolder metaData = new TaskHolder(cycles, delays, task);

Queue tasks = taskHolders.get(index);

synchronized (tasks) {

tasks.add(metaData);

}

}

public int tick() {

currentTick = (currentTick + 1) % ticks;

return currentTick;

}

public Queue getCurrentTasks() {

return taskHolders.get(currentTick);

}

public int getCurrentTick() {

return currentTick;

}

public int getTicks() {

return ticks;

}

public int getTickDuration() {

return tickDuration;

}

@Override

public String toString() {

return "TimerContext [timers=" + taskHolders + ", ticks=" + ticks + ", tickDuration=" + tickDuration

+ ", currentTick=" + currentTick + "]";

}

}

3,TimerScheduler.javapackage com.zws.timer;

import java.io.IOException;

import java.util.Iterator;

import java.util.Queue;

import java.util.Timer;

import java.util.TimerTask;

/**

* 用于判断定时器是否到时、执行任务、维护定时器状态。

* @author wensh.zhu

* @date 2018-04-22

*/

public class TimerScheduler extends TimerTask {

private TimerContext timerContext;

public TimerScheduler() {}

public TimerScheduler(TimerContext timerContext) {

this.timerContext = timerContext;

}

/**

* 定时检测,如果定时器触发时间到了就从集合中删除并执行任务,否则圈数减一。

*/

@Override

public void run() {

if (timerContext == null)

return;

Queue tasks = timerContext.getCurrentTasks();

synchronized (tasks) {

Iterator itor = tasks.iterator();

while (itor.hasNext()) {

TaskHolder timer = itor.next();

if (timer.isTimeOut()) {

itor.remove();

new Thread(timer.getTask()).start();

} else {

timer.cutDown();

}

}

}

timerContext.tick();

}

public void addTask(Runnable task, int delays) {

timerContext.addTask(task, delays);

}

public TimerContext getTimerContext() {

return timerContext;

}

public void setTimerContext(TimerContext timerContext) {

this.timerContext = timerContext;

}

public static void main(String[] args) throws IOException {

TimerContext context = new TimerContext(60, 1);

TimerScheduler sheduler = new TimerScheduler(context);

sheduler.addTask(new Runnable() {

public void run() {

System.out.println(DateUtils.now());

}

}, 60);

System.out.println(DateUtils.now());

Timer timer = new Timer();

timer.scheduleAtFixedRate(sheduler, 0, context.getTickDuration() * 1000L);

System.in.read();

}

}

4,DateUtils.javapackage com.zws.timer;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

/**

*

* @author wensh.zhu

* @date 2018-04-22

*/

public class DateUtils {

public static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";

public static String now() {

LocalDateTime time = LocalDateTime.now();

return time.format(DateTimeFormatter.ofPattern(DEFAULT_PATTERN));

}

public static String plusSeconds(int seconds) {

LocalDateTime time = LocalDateTime.now();

time.plusSeconds(seconds);

return time.format(DateTimeFormatter.ofPattern(DEFAULT_PATTERN));

}

}

转载地址:https://blog.csdn.net/weixin_35600779/article/details/114457520 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:java hibernate 查询_(十)Hibernate 查询方式
下一篇:java命令行解析库_Java命令行解析:apache commons-cli

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年03月27日 15时01分43秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章