Java实现定时任务

为什么要用定时任务


项目中要在内存中实现一个数据缓存机制,然后要定期定时清理其中无效的数据,因为项目没用Spring框架不能集成Quartz(个人认为很好用的三方库),所以第一次系统的了解一下Java自带的一些函数来实现定时任务。

Java中定时任务有哪几种方式


  1. 单开一个线程一直运行,通过sleep达到定时效果

    不太好用

  2. 用Timer和TimerTask (jdk1.3之后使用)

    优势:

    • 当启动和去取消任务时可以控制
    • 第一次执行任务时可以指定你想要的delay时间
  3. ScheduledExecutorService (jdk5后使用,非常适合并发使用)

    优势:

    • 相比于Timer的单线程,它是通过线程池的方式来执行任务的
    • 可以很灵活的去设定第一次执行任务delay时间
    • 提供了良好的约定,以便设定执行的时间间隔

具体实现


1
2
3
4
5
6
7
ScheduledExecutorService execService = Executors
.newScheduledThreadPool( 2 );

String time = "2018-08-06 00:00:00"

execService.scheduleAtFixedRate( new CacheTask(),
getInitialDelay( time ), getDayMillis( 1 ), TimeUnit.MILLISECONDS );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 将具体时间转换为毫秒
private static long getInitialDelay( String time )
{
Date specifiedDate = getTimeMillis( time );
if( specifiedDate.before( new Date() ) )
{
Calendar calendar = Calendar.getInstance();
calendar.setTime( specifiedDate );
calendar.add( Calendar.DAY_OF_MONTH, 1 );
return calendar.getTime().getTime() - System.currentTimeMillis();
}

return specifiedDate.getTime() - System.currentTimeMillis();
}


private static Date getTimeMillis( String time )
{
try
{
DateFormat dateFormat = new SimpleDateFormat( "yy-MM-dd HH:mm:ss" );
DateFormat dayFormat = new SimpleDateFormat( "yy-MM-dd" );
return dateFormat
.parse( dayFormat.format( new Date() ) + " " + time );
}
catch( ParseException e )
{
logger.error( "getTimeMillis failed" );
}
return new Date();
}
1
2
3
4
5
// 将时间间隔转换为毫秒
private static long getDayMillis( int num )
{
return num * 24 * 60 * 60 * 1000;
}

解释


1
2
execService.scheduleAtFixedRate( new CacheTask(),
getInitialDelay( time ), getDayMillis( 1 ), TimeUnit.MILLISECONDS );

这段代码的参数从前往后依次是:到时间了要执行的程序(单独一个线程),设置开始时间,时间间隔,单位。

然后还要注意scheduleAtFixedRate方法和scheduleWithFixedDelay 方法的区别:

scheduleAtFixedRate是每次定时任务执行的时间都是固定间隔,而scheduleWithFixedDelay 则是收到每次执行的线程时间的影响,意思就是下一次定时任务的执行开始时间是上一次任务的结束时间+指定的时间间隔,这样就会存在延时,程序执行时间不确定的问题。

zhangxingrui wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!