java根据始末年份获得中间年份_Java Timer 到 Executors.newScheduledThreadPool 定时任务和周期任务...

前言

定时任务里肯定可以查到 Timer ,关于 Timer 的介绍,有很多很详细的,我这里打算对该类进行演进,先从这个最简单的定时工具讲起,逐步实现定时任务的功能,周期性任务计划,多任务周期性计划。

起因

起因是因为我现在的项目上有周期性日程计划,但是计划了时间却不能准确进行,于是我打算自己试试写一个,而且由于我对 Timer 和 Thread 不是很熟悉,所以打算一步步演进项目,先从小的步骤开始进行,计划步骤如下:

第一步:实现1秒执行一次,总共执行三次

第二步:设置时间,到期执行

第三步:设置三个时间,三个任务,到期都要执行,产生不同的log文件,然后周期化,先设置成每天,然后每周

第四步:如果有成千上万个任务,如果降低线程的使用率,目前的想法是给执行任务的先后任务排序,最先执行的,先计时

第五步:网页界面,按钮:开始任务,任务临时退出(任务还继续,但是系统需要关闭一次,希望下次启动系统时继续任务,很可能出现启动系统时,本该执行的任务错过了执行时间,记录日志)

代码

于是本篇先实现前两步。

第一步很简单代码如下:

public class TimerTest03 {

Timer timer;

public TimerTest03(){

timer = new Timer();

timer.schedule(new TimerTaskTest03(), 1000, 2000);

}

public static void main(String[] args) {

new TimerTest03();

}

public class TimerTaskTest03 extends TimerTask{

int count=0;

@Override

public void run() {

Date date = new Date(this.scheduledExecutionTime());

System.out.println("本次执行该线程的时间为:" + date);

count++;

if(count==3) {

this.cancel();

}

}

}

}

第二步也不难,只需要知道:schedule(TimerTask task, Date time)-安排在指定的时间执行指定的任务。

public class TimeScheduleTask {

Timer timer;

public TimeScheduleTask(Date scheduledTime) {

System.out.println("指定时间time=" + scheduledTime);

timer = new Timer();

timer.schedule(new TimerTaskTest(), scheduledTime);

}

public class TimerTaskTest extends TimerTask {

@Override

public void run() {

System.out.println("指定时间执行线程任务...");

}

}

public static void main(String[] args) {

// 创建 Calendar 对象

Calendar calendar = Calendar.getInstance();

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-M-d H:m:s");

// 指定一个日期

Date date;

try {

date = dateFormat.parse("2019-8-30 09:25:16");

// 对 calendar 设置为 date 所定的日期

calendar.setTime(date);

new TimeScheduleTask(calendar.getTime());

} catch (ParseException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

优缺点

Timer 是基于绝对时间,对系统时间特别敏感,在现在的项目里都是对日期有要求的,所以绝对时间是没有问题的,但是 Timer 内部是单一线程的,发生异常就会终止全部任务,于是给出了一个比较优秀的解决办法,就是使用 ScheduledThreadPoolExecutor ,这样就可以支持多任务了。

ScheduledExecutorService scheduExec=Executors.newScheduledThreadPool(2);

我们可以看看官方的解释

public static ExecutorService newFixedThreadPool(int nThreads)

Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.

Parameters:

nThreads - the number of threads in the pool

Returns:

the newly created thread pool

Throws:

IllegalArgumentException - if nThreads <= 0

整理

上面的代码只是演示,我们需要提取我们需要的部分,我们希望实现的功能有,指定一个开始日期,这个日期是实际的日期,也就是服务器的时间,然后开始一个任务,这个任务是周期性的。为了不再是控制台打印,我将任务的内容改为记录日志,这样可以方便记录时间和产生文字内容。

任务代码:

public class ScheduleTask extends Thread {

public void run() {

CaeLogger.WriteLog("ScheduleTask", "goo");

}

}

周期性任务:

public class ScheduledExecutorTest {

private ScheduledExecutorService scheduExec;

private ScheduleTask myTask;

ScheduledExecutorTest(long num) {

this.scheduExec = Executors.newScheduledThreadPool(1);

myTask = new ScheduleTask();

scheduExec.scheduleAtFixedRate(myTask, 0, num, TimeUnit.MINUTES);

}

public void startTask() {

myTask.start();

}

public void endTask() {

// 关闭具体任务线程

myTask.interrupt();

// 关闭周期计划

scheduExec.shutdown();

}

}

为了方便我做测试,我把改任务的周期设置为固定值,而且是每隔一分钟执行一次。下面是开始时间和结束时间主类:

public class TimeScheduleTask {

Timer timer;

Timer timerEnd;

ScheduledExecutorTest myTask;

TimerTaskTest1 timerF;

public TimeScheduleTask(Date startTime, Date endTime) {

System.out.println("指定时间time=" + startTime);

CaeLogger.WriteLog("startTie", "XX");

timer = new Timer();

timerEnd = new Timer();

timerF = new TimerTaskTest1();

timer.schedule(timerF, startTime);

timerEnd.schedule(new TimerTaskTest2(), endTime);

}

public class TimerTaskTest1 extends TimerTask {

@Override

public void run() {

myTask = new ScheduledExecutorTest(1);

myTask.startTask();

}

}

public class TimerTaskTest2 extends TimerTask {

@Override

public void run() {

if (myTask != null) {

myTask.endTask();

timerF.cancel();

this.cancel();

}

}

}

public static void main(String[] args) {

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-M-d H:m:s");

// 指定一个日期

Date date;

Date date1;

try {

date = dateFormat.parse("2019-8-30 14:54:00");

date1 = dateFormat.parse("2019-8-30 14:59:00");

new TimeScheduleTask(date, date1);

} catch (ParseException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

结果:记录已产生,而且是到结束时间就停止了看图

AAffA0nNPuCLAAAAAElFTkSuQmCC

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值