1
回答
通过java concurrent实现定时任务
华为云实践训练营,热门技术免费实践!>>>   

定时任务有两种:

  1. 固定延时的定时任务,即一个任务结束等待固定时间后再执行下一个;
  2. 固定频率的定时任务,即任务在固定时常后开始执行。

举个例子,好比列车调度,比如上海到北京的列车,从上海到达北京后,休息10小时再返回,这就相当于固定延时的定时任务;如果从上海出发是下午3点,到达北京后,比如是上午5点,下午3点再返回上海,这就是固定频率的任务。

这里要注意,固定频率定时任务并不会并发,还是用列车调度举例,如果列车晚点,下午4点到北京,固定频率定时任务并不是在下午3点再调度一列新车发往上海,而是延误的列车到京后立即出发返回。而固定延时是即使延误也要休息10小时后再出发。

如果没有java concurrent api,那么就要使用java.util.Timer相关的API,比较繁琐。前者更简明。

先来看一个定时固定延时任务的示例:

package com.easymorse.concurrent; 

import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

public class DelayDemo { 

    private int count; 

    private ScheduledExecutorService executorService; 

    public DelayDemo() { 
        this.executorService = Executors.newScheduledThreadPool(5); 
        this.executorService.scheduleWithFixedDelay(new Runnable() { 

            @Override 
            public void run() { 
                int index = ++count; 
                System.out.println(index + " – run task …"); 
                try { 
                    Thread.sleep(1000); 
                } catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
                System.out.println(index + " – task end."); 
            } 
        }, 1000, 1000, TimeUnit.MILLISECONDS); 
    } 

    public static void main(String[] args) { 
        new DelayDemo(); 
    } 
}

线程池里面有2个线程:

this.executorService = Executors.newScheduledThreadPool(2);

其实没必要,因为有一个总是空闲的。如果有多个定时任务,可考虑加到线程数,只有一个的话,设置一个线程就够用了。演示打印的结果:

1 – run task …
1 – task end.
2 – run task …
2 – task end.
3 – run task ...

可以看到任务结束后是延时固定时间后开始的。

示例源代码见:

http://easymorse.googlecode.com/svn/tags/concurrent.demo-0.3/

只需将创建定时任务这行替代为:

this.executorService.scheduleAtFixedRate(new Runnable() {
...
});

即可实现固定频率的定时任务示例,因为线程sleep了1秒,而间隔是1秒,因此会看到一个任务结束后,没有停留立即开始新的任务。

关闭定时任务可以使用以下任一方式:

executorService.shutdown(); 
executorService.shutdownNow();

其中shutdown将等待任务结束,shutdownNow立即中止任务的执行。

但是这样也有问题,如果有多个定时任务,只想关闭其中一个呢?可以这样:

ScheduledFuture scheduledFuture = this.executorService 
                .scheduleAtFixedRate(new Runnable() {
 
…

scheduleAtFixedRate或者scheduleWithFixedDelay方法会返回一个ScheduledFuture实例。

在需要关闭该定时任务的时候调用:

scheduledFuture.cancel(true);

这里的true表示如果定时任务在执行,立即中止,false则等待任务结束后再停止。

举报
鉴客
发帖于6年前 1回/2K+阅
顶部