ScheduledExecutorService - 定时周期执行任务

ScheduleExecutorService接口中有四个重要的方法,其中scheduleAtFixedRatescheduleWithFixedDelay在实现定时程序(每隔一段时间执行一次)时比较方便。

接口中四个方法如下:

该接口中前两个方法只会执行一次,后两个方法会定时循环执行。

 — 三个方法简介—

1. ScheduledFuture<?> schedule(
        Runnable command,
        long delay,
        TimeUnit unit
)

定义:在给定的延时之后,创建并执行一个启动一次性动作。
参数:
参数一(Runnable):命令执行的任务。
参数二(delay)       :延迟执行的时间。 
参数三(TimerUnit):延时蚕食的时间单位。

例:
在若依框架中,封装了一个异步打印日志的类,就是用到了schedule()方法:

public class AsyncManger{
    // ··· ···
    // 从ioc容器中获取 bean,注:SpringUtils也是若依框架封装的,通过名称来获取bean(可
    // 以通过首字母小写形式根据名称来获取ioc容器中的bean)
    private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
    // 延迟20毫秒,执行任务类,在任务类中会去 insert 信息。
    public viod execute(TimerTask task) {
        executor.schedule(task, 20, TimeUnit.MILLISECONDS);
    }
}

2. ScheduledFuture<?> scheduleAtFixedRate(
        Runnable command,
        long initialDelay,
        long period,
        TimeUnit unit
)

定义:创建并执行一个周期性的操作。

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

3. ScheduledFuture<?> scheduleWithFixedDelay(
        Runnable command,
        long initialDelay,
        long delay,
        TimeUnit unit
)

定义:创建并执行一个周期性的操作。

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

 

 — 功能 —

1. 每隔多长时间重新执行一次任务。
初始延时0毫秒,每隔1000毫秒重新执行一次任务:


/**
 * 以固定周期频率执行任务
 */
public class Test {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleAtFixedRate(
            Test.timerTask(), 0, 1000, TimeUnit.MILLISECONDS
        );
    }
    public static TimerTask timerTask () {
        return new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行了");
            }
        };
    }
}

问题:
如果要执行的任务时间大于间隔时间,会如何处理呢?
其实当执行任务的时间大于我们指定的间隔时间时,它并不会在指定间隔时开辟一个新的线程并发执行这个任务,而是等待该线程执行完毕。
源码注释:
If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
如果此任务的任何执行时间超过其周期,则后续执行可能开始较晚,但不会并发执行。  

关于创建线程池:
创建一个线程池,该线程池可以调度命令在给定的延时后运行或定期执行。
参数:corePoolSize - 保持在池中的线程数,即使他们是空闲的。
返回:新创建的调度线程池。
抛出:如果corePoolSize < 0 ,IllegalArgumentException 

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);

关于 IllegalArgumentException 异常:

Illegal Argument Exception 非法参数异常。

2. 按照指定频率间隔执行某个任务。
初始化延时0ms开始,本次执行结束后延迟1000ms开始下次执行,注意:必须等到本次任务执行完毕才能开始延时且开始下一次任务执行。


/**
 * 以固定延迟时间进行执行
 * 本次任务执行完成后,需要延迟设定的延迟时间,才会执行新的任务
 * 下边代码,延时0毫秒开始执行timerTask() 方法,Thread.sleep(2000) 暂停2000毫秒,之后才开始
 * 延时1000毫秒,执行下一次任务。
 */
public class Test {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleWithFixedDelay(
            Test.timerTask(), 0, 1000, TimeUnit.MILLISECONDS
        );
    }
    public static TimerTask timerTask () {
        return new TimerTask() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("执行了");
            }
        };
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值