From df5dba838402ebd811fc14ffbeb88d1229277d34 Mon Sep 17 00:00:00 2001 From: lxyer <237809796@qq.com> Date: Sun, 12 Aug 2018 01:37:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8D=87=E7=BA=A7,=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E4=BB=BB=E5=8A=A1=E6=89=A7=E8=A1=8C=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E7=9A=84=E5=8F=98=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 25 +++++----- .../java/com/lxyer/timer/AbstractTask.java | 8 ++++ src/main/java/com/lxyer/timer/Task.java | 29 ++++++++++++ .../java/com/lxyer/timer/TimerExecutor.java | 14 +++++- src/main/java/com/lxyer/timer/TimerQueue.java | 18 ++++++-- .../lxyer/timer/scheduled/ScheduledCycle.java | 15 +++++- .../timer/scheduled/ScheduledExpres.java | 13 ++++-- src/test/java/com/lxyer/timer/TimerTest.java | 46 +++++++++++++++---- 8 files changed, 137 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index d54c832..04833ae 100644 --- a/README.md +++ b/README.md @@ -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);//添加任务 task1,task2 ``` -#### 参与贡献 -你可以做这些 -1. Fork 本项目 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request -5. **提出你的宝贵意见** + +支持定时计划修改 +``` +//修改a1 每2s执行一次 +task.setScheduled(new ScheduledCycle(2000 * 1)); +timerExecutor.add(task); +``` +请看测试案例,以及阅读详细源码,所有的代码也就几百行; #### 关于 redbbs 交流群:527523235 diff --git a/src/main/java/com/lxyer/timer/AbstractTask.java b/src/main/java/com/lxyer/timer/AbstractTask.java index faa6535..725abb6 100644 --- a/src/main/java/com/lxyer/timer/AbstractTask.java +++ b/src/main/java/com/lxyer/timer/AbstractTask.java @@ -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; } } diff --git a/src/main/java/com/lxyer/timer/Task.java b/src/main/java/com/lxyer/timer/Task.java index 81b5936..d20fe60 100644 --- a/src/main/java/com/lxyer/timer/Task.java +++ b/src/main/java/com/lxyer/timer/Task.java @@ -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(); } diff --git a/src/main/java/com/lxyer/timer/TimerExecutor.java b/src/main/java/com/lxyer/timer/TimerExecutor.java index 13ae446..124d863 100644 --- a/src/main/java/com/lxyer/timer/TimerExecutor.java +++ b/src/main/java/com/lxyer/timer/TimerExecutor.java @@ -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(()->{ diff --git a/src/main/java/com/lxyer/timer/TimerQueue.java b/src/main/java/com/lxyer/timer/TimerQueue.java index fb55343..8df62eb 100644 --- a/src/main/java/com/lxyer/timer/TimerQueue.java +++ b/src/main/java/com/lxyer/timer/TimerQueue.java @@ -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; } } diff --git a/src/main/java/com/lxyer/timer/scheduled/ScheduledCycle.java b/src/main/java/com/lxyer/timer/scheduled/ScheduledCycle.java index bb3bd4d..ace8215 100644 --- a/src/main/java/com/lxyer/timer/scheduled/ScheduledCycle.java +++ b/src/main/java/com/lxyer/timer/scheduled/ScheduledCycle.java @@ -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 diff --git a/src/main/java/com/lxyer/timer/scheduled/ScheduledExpres.java b/src/main/java/com/lxyer/timer/scheduled/ScheduledExpres.java index 38cf7d8..e2e6b9a 100644 --- a/src/main/java/com/lxyer/timer/scheduled/ScheduledExpres.java +++ b/src/main/java/com/lxyer/timer/scheduled/ScheduledExpres.java @@ -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 diff --git a/src/test/java/com/lxyer/timer/TimerTest.java b/src/test/java/com/lxyer/timer/TimerTest.java index 7ac39df..7045cc9 100644 --- a/src/test/java/com/lxyer/timer/TimerTest.java +++ b/src/test/java/com/lxyer/timer/TimerTest.java @@ -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(); }