优化升级,支持任务执行计划的变更

This commit is contained in:
lxyer 2018-08-12 01:37:55 +08:00
parent b4603fa8f9
commit df5dba8384
8 changed files with 137 additions and 31 deletions

View File

@ -1,7 +1,7 @@
# redtimer
#### 项目介绍
redtimer是本人纯手工精心编写的一个任务定时调度器
redtimer是本人纯手工精心编写的一个任务定时调度器全部代码均自己编写实现;
功能包含**定时和时间解析**两部分功能;
编写她的意图,用更少的代码满足自己的业务功能需求,让其他业务代码更佳的随心所欲;
@ -13,19 +13,22 @@ redtimer是本人纯手工精心编写的一个任务定时调度器
#### 安装使用教程
创建启动定时任务
```
TimerExecutor timerExecutor = new TimerExecutor(1);
timerExecutor.add(new TaskImpl("a1", new ScheduledExpres("0 2 * * *"));//定时每天2点执行
timerExecutor.start();
请看测试案例,以及阅读详细源码,所有的代码也就几百行;
Task task1 = new TaskImpl("a1", new ScheduledExpres("1-40 * * * *"));//1-40定时每分钟执行
Task task2 = new TaskImpl("a1", new ScheduledCycle(1000 * 5));//a2定时每5s执行
timerExecutor.add(task1, task2);//添加任务 task1task2
```
#### 参与贡献
你可以做这些
1. Fork 本项目
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
5. **提出你的宝贵意见**
支持定时计划修改
```
//修改a1 每2s执行一次
task.setScheduled(new ScheduledCycle(2000 * 1));
timerExecutor.add(task);
```
请看测试案例,以及阅读详细源码,所有的代码也就几百行;
#### 关于
redbbs 交流群527523235

View File

@ -24,6 +24,12 @@ public abstract class AbstractTask implements Task {
return name;
}
@Override
public void setScheduled(Scheduled scheduled) {
this.scheduled = scheduled;
this.theTime = scheduled.theTime().toInstant(ZoneOffset.of("+8")).toEpochMilli();
}
@Override
public long nextTime(){
LocalDateTime next = scheduled.nextTime();
@ -35,6 +41,8 @@ public abstract class AbstractTask implements Task {
}
@Override
public long theTime(){
LocalDateTime next = scheduled.theTime();
this.theTime = next.toInstant(ZoneOffset.of("+8")).toEpochMilli();
return theTime;
}
}

View File

@ -1,12 +1,41 @@
package com.lxyer.timer;
import com.lxyer.timer.scheduled.Scheduled;
/**
* @author: liangxianyou at 2018/8/5 19:32.
*/
public interface Task extends Runnable{
/**
* 得到任务名称
*
* @return
*/
String getName();
/**
* 设置任务执行计划
*
* @param scheduled
*/
void setScheduled(Scheduled scheduled);
/**
* 得到下一次执行计划的时间并设置thenTime
* @return
*/
long nextTime();
/**
* 任务即将执行的时间点
*
* @return
*/
long theTime();
/**
* 执行任务
*/
void run();
}

View File

@ -12,16 +12,26 @@ public class TimerExecutor {
public TimerExecutor(int n) {
executor = Executors.newFixedThreadPool(n);
start();
}
public void add(Task task){
queue.put(task);
public void add(Task ... task){
for (Task t : task) {
queue.put(t);
}
}
private void add(Task task, boolean upTime){
if (upTime) task.nextTime();
queue.put(task);
}
public Task remove(String name){
return queue.remove(name);
}
public Task get(String name){
return queue.get(name);
}
public void start() {
new Thread(()->{

View File

@ -7,6 +7,7 @@ import java.util.Set;
/**
* Created by liangxianyou at 2018/7/23 14:07.
*/
@SuppressWarnings("Duplicates")
class TimerQueue{
Object lock = new Object();
Task[] queue = new Task[128];
@ -26,7 +27,6 @@ class TimerQueue{
for (int i = size+1; i > inx; i--) {
queue[i] = queue[i-1];
queue[i-1] = null;
}
queue[inx] = task;
@ -38,7 +38,7 @@ class TimerQueue{
Task take() throws InterruptedException {
synchronized (lock){
if (size == 0) lock.wait();
while (size == 0) lock.wait(10);//循环避免非put线程唤醒空异常
long currentTime = System.currentTimeMillis();
long nextTime = queue[0].theTime();
@ -59,21 +59,33 @@ class TimerQueue{
}
Task remove(String name){
return get(name, true);
}
Task get(String name){
return get(name, false);
}
private Task get(String name, boolean remove) {
synchronized (lock){
if(!names.contains(name)) return null;
Task take = null;
for (int i = 0; i < size-1; i++) {
for (int i = 0; i < size; i++) {
if (name.equals(queue[i].getName())){
take = queue[i];
if (!remove) break;
while (i < size+1){
queue[i] = queue[i+1];
queue[i+1] = null;
i++;
}
names.remove(name);
size--;
break;
}
}
lock.notify();
return take;
}
}

View File

@ -11,7 +11,18 @@ public class ScheduledCycle implements Scheduled {
private LocalDateTime theTime;
private long period;
private TemporalUnit unit = ChronoUnit.SECONDS;
private TemporalUnit unit = ChronoUnit.MILLIS;
public ScheduledCycle(long period) {
this.theTime = LocalDateTime.now();
this.period = period;
}
public ScheduledCycle(long period,TemporalUnit unit) {
this.theTime = LocalDateTime.now();
this.period = period;
this.unit = unit;
}
public ScheduledCycle(LocalDateTime startTime, long period) {
this.theTime = startTime;
@ -25,7 +36,7 @@ public class ScheduledCycle implements Scheduled {
@Override
public LocalDateTime nextTime() {
return theTime.plus(period, unit);
return theTime = theTime.plus(period, unit);
}
@Override

View File

@ -21,24 +21,27 @@ public class ScheduledExpres implements Scheduled{
private int[] days;
private int[] monthes;
private int[] weeks;
private String[] cfgArr;
private String cfg;
private String[] cfgArr;
private LocalDateTime theTime;
private int _y,_M,_d,_H,_m;
public ScheduledExpres(String cfg){
this.cfg = cfg;
this.theTime = LocalDateTime.now();
initTheTime(cfg);
initTheTime();
}
public ScheduledExpres(final LocalDateTime startTime, String cfg){
LocalDateTime now = LocalDateTime.now();
this.theTime = now.isAfter(startTime)? now : startTime;
initTheTime(cfg);
this.cfg = cfg;
initTheTime();
}
//寻找初始合法时间
public void initTheTime( String cfg) {
public void initTheTime() {
year = theTime.getYear();
month = theTime.getMonthValue();
cfgArr = cfg.split(" ");
@ -103,7 +106,7 @@ public class ScheduledExpres implements Scheduled{
*/
@Override
public LocalDateTime nextTime(){
return carry("m");
return theTime = carry("m");
}
@Override

View File

@ -1,5 +1,6 @@
package com.lxyer.timer;
import com.lxyer.timer.scheduled.ScheduledCycle;
import com.lxyer.timer.scheduled.ScheduledExpres;
import org.junit.Test;
@ -19,16 +20,24 @@ public class TimerTest {
* 启动定时器测试
*/
@Test
public void t2(){
public void t2() throws InterruptedException {
TimerExecutor timerExecutor = new TimerExecutor(1);
timerExecutor.add(new TaskImpl("a1", new ScheduledExpres(LocalDateTime.now(), "1-40/2 * * * *")));//1-40定时每分钟执行
timerExecutor.start();
Task t1 = new TaskImpl("a1", new ScheduledExpres("1-40 * * * *"));//1-40定时每分钟执行
TaskImpl t2 = new TaskImpl("a2", new ScheduledCycle(5000 * 1));
try {
Thread.sleep(1500_000000);
} catch (InterruptedException e) {
e.printStackTrace();
timerExecutor.add(t1, t2);
//60s后修改a1 每2s执行一次
Thread.sleep(1000 * 60);
//task = timerExecutor.get("a1");
if (t1 != null){
t1.setScheduled(new ScheduledCycle(2000 * 1));
timerExecutor.add(t1);
}
Thread.sleep(1500_000000);
}
/**
@ -133,7 +142,28 @@ public class TimerTest {
08 18 * 7,8 4
"task1", "1 22-23 * * 7"
*/
Task task = new TaskImpl("task1", new ScheduledExpres("1 22-23 * * 7"));
Task task = new TaskImpl("task1", new ScheduledExpres("1 22-23 * * 7")){
@Override
public void run() {
System.out.println("----");
System.out.println(new SimpleDateFormat("0: yyyy-MM-dd HH:mm:ss").format(theTime()));
System.out.println(new SimpleDateFormat("1: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("2: yyyy-MM-dd HH:mm:ss").format(nextTime()));
/*System.out.println(new SimpleDateFormat("3: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("4: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("5: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("6: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("7: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("8: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("9: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("10: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("11: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("12: yyyy-MM-dd HH:mm:ss").format(nextTime()));
System.out.println(new SimpleDateFormat("13: yyyy-MM-dd HH:mm:ss").format(nextTime()));*/
}
};
task.run();
task.setScheduled(new ScheduledCycle(1000 * 5));//定时每秒执行
task.run();
}