Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2293358
  • 博文数量: 321
  • 博客积分: 3440
  • 博客等级: 中校
  • 技术积分: 2992
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-24 09:08
个人简介

我就在这里

文章分类

全部博文(321)

文章存档

2015年(9)

2014年(84)

2013年(101)

2012年(25)

2011年(29)

2010年(21)

2009年(6)

2008年(23)

2007年(23)

分类: Java

2014-11-11 15:38:04

一:简单说明

ScheduleExecutorService接口中有四个重要的方法,其中scheduleAtFixedRate和scheduleWithFixedDelay在实现定时程序时比较方便。

下面是该接口的原型定义

java.util.concurrent.ScheduleExecutorService extends ExecutorService extends Executor

接口scheduleAtFixedRate原型定义及参数说明

  1. public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
  2.                 long initialDelay,
  3.                 long period,
  4.                 TimeUnit unit);

command:执行线程
initialDelay:初始化延时
period:两次开始执行最小间隔时间
unit:计时单位

接口scheduleWithFixedDelay原型定义及参数说明

  1. public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
  2.                 long initialDelay,
  3.                 long delay,
  4.                 TimeUnit unit);

command:执行线程
initialDelay:初始化延时
period:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)
unit:计时单位

二:功能示例

1.按指定频率周期执行某个任务。

初始化延迟0ms开始执行,每隔100ms重新执行一次任务。

  1. /**
  2.  * 以固定周期频率执行任务
  3.  */
  4. public static void executeFixedRate() {
  5.     ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
  6.     executor.scheduleAtFixedRate(
  7.             new EchoServer(),
  8.             0,
  9.             100,
  10.             TimeUnit.MILLISECONDS);
  11. }
间隔指的是连续两次任务开始执行的间隔。

2.按指定频率间隔执行某个任务。

初始化时延时0ms开始执行,本次执行结束后延迟100ms开始下次执行。


  1. /**
  2.      * 以固定延迟时间进行执行
  3.      * 本次任务执行完成后,需要延迟设定的延迟时间,才会执行新的任务
  4.      */
  5.     public static void executeFixedDelay() {
  6.         ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
  7.         executor.scheduleWithFixedDelay(
  8.                 new EchoServer(),
  9.                 0,
  10.                 100,
  11.                 TimeUnit.MILLISECONDS);
  12.     }

3.周期定时执行某个任务。

有时候我们希望一个任务被安排在凌晨3点(访问较少时)周期性的执行一个比较耗费资源的任务,可以使用下面方法设定每天在固定时间执行一次任务。


  1. /**
  2.      * 每天晚上8点执行一次
  3.      * 每天定时安排任务进行执行
  4.      */
  5.     public static void executeEightAtNightPerDay() {
  6.         ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
  7.         long oneDay = 24 * 60 * 60 * 1000;
  8.         long initDelay = getTimeMillis("20:00:00") - System.currentTimeMillis();
  9.         initDelay = initDelay > 0 ? initDelay : oneDay + initDelay;
  10.       
  11.         executor.scheduleAtFixedRate(
  12.                 new EchoServer(),
  13.                 initDelay,
  14.                 oneDay,
  15.                 TimeUnit.MILLISECONDS);
  16.     }

  1. **
  2.  * 获取指定时间对应的毫秒数
  3.  * @param time "HH:mm:ss"
  4.  * @return
  5.  */
  6. private static long getTimeMillis(String time) {
  7.     try {
  8.         DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
  9.         DateFormat dayFormat = new SimpleDateFormat("yy-MM-dd");
  10.         Date curDate = dateFormat.parse(dayFormat.format(new Date()) + " " + time);
  11.         return curDate.getTime();
  12.     } catch (ParseException e) {
  13.         e.printStackTrace();
  14.     }
  15.     return 0;
  16. }
4.辅助代码

  1. class EchoServer implements Runnable {
  2.     @Override
  3.     public void run() {
  4.         try {
  5.             Thread.sleep(50);
  6.         } catch (InterruptedException e) {
  7.             e.printStackTrace();
  8.         }
  9.         System.out.println("This is a echo server. The current time is " +
  10.                 System.currentTimeMillis() + ".");
  11.     }
  12. }

三:一些问题

上面写的内容有不严谨的地方,比如对于scheduleAtFixedRate方法,当我们要执行的任务大于我们指定的执行间隔时会怎么样呢?

对于中文API中的注释,我们可能会被忽悠,认为无论怎么样,它都会按照我们指定的间隔进行执行,其实当执行任务的时间大于我们指定的间隔时间时,它并不会在指定间隔时开辟一个新的线程并发执行这个任务。而是等待该线程执行完毕。

源码注释如下:


  1. * Creates and executes a periodic action that becomes enabled first
  2.     * after the given initial delay, and subsequently with the given
  3.     * period; that is executions will commence after
  4.     * <tt>initialDelay</tt> then <tt>initialDelay+period</tt>, then
  5.     * <tt>initialDelay + 2 * period</tt>, and so on.
  6.     * If any execution of the task
  7.     * encounters an exception, subsequent executions are suppressed.
  8.     * Otherwise, the task will only terminate via cancellation or
  9.     * termination of the executor. If any execution of this task
  10.     * takes longer than its period, then subsequent executions
  11.     * may start late, but will not concurrently execute.

根据注释中的内容,我们需要注意的时,我们需要捕获最上层的异常,防止出现异常中止执行,导致周期性的任务不再执行。

四:除了我们自己实现定时任务之外,我们可以使用Spring帮我们完成这样的事情。

Spring自动定时任务配置方法(我们要执行任务的类名为com.study.MyTimedTask)


  1. <bean id="myTimedTask" class="com.study.MyTimedTask"/>

  1. <bean id="doMyTimedTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  2.     <property name="targetObject" ref="myTimedTask"/>
  3.     <property name="targetMethod" value="execute"/>
  4.     <property name="concurrent" value="false"/>
  5. </bean>

  1. <bean id="myTimedTaskTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
  2.         <property name="jobDetail" ref="doMyTimedTask"/>
  3.         <property name="cronExpression" value="0 0 2 * ?"/>
  4.     </bean>

  1. <bean id="doScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  2.         <property name="triggers">
  3.             <list>
  4.                 <ref local="myTimedTaskTrigger"/>
  5.             </list>
  6.         </property>
  7.     </bean>

  1. <bean id="doScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  2.     <property name="triggers">
  3.         <list>
  4.             <bean class="org.springframework.scheduling.quartz.CronTriggerBean">
  5.                 <property name="jobDetail"/>
  6.                     <bean id="doMyTimedTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  7.                         <property name="targetObject">
  8.                             <bean class="com.study.MyTimedTask"/>
  9.                         </property>
  10.                         <property name="targetMethod" value="execute"/>
  11.                         <property name="concurrent" value="false"/>
  12.                     </bean>
  13.                 </property>
  14.                 <property name="cronExpression" value="0 0 2 * ?"/>
  15.             </bean>
  16.         </list>
  17.     </property>
  18. </bean>













阅读(926) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~