ScheduledExecutorService定时周期运行指定的任务

一:简单说明

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

以下是该接口的原型定义

java.util.concurrent.ScheduleExecutorService extends ExecutorService extends Executor

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

[java] view
plain
copy

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

command:运行线程

initialDelay:初始化延时

period:两次開始运行最小间隔时间

unit:计时单位

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

[java] view
plain
copy

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

command:运行线程

initialDelay:初始化延时

period:前一次运行结束到下一次运行開始的间隔时间(间隔运行延迟时间)

unit:计时单位

二:功能演示样例

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

初始化延迟0ms開始运行,每隔100ms又一次运行一次任务。

[java] view
plain
copy

  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開始下次运行。

[java] view
plain
copy

  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点(訪问较少时)周期性的运行一个比較耗费资源的任务,能够使用以下方法设定每天在固定时间运行一次任务。

[java] view
plain
copy

  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. executor.scheduleAtFixedRate(
  11. new EchoServer(),
  12. initDelay,
  13. oneDay,
  14. TimeUnit.MILLISECONDS);
  15. }

[java] view
plain
copy

  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.辅助代码

[java] view
plain
copy

  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中的凝视,我们可能会被忽悠,觉得不管怎么样,它都会依照我们指定的间隔进行运行,事实上当运行任务的时间大于我们指定的间隔时间时,它并不会在指定间隔时开辟一个新的线程并发运行这个任务。而是等待该线程运行完成。

源代码凝视例如以下:

[java] view
plain
copy

  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)

[html] view
plain
copy

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

[html] view
plain
copy

  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>

[html] view
plain
copy

  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>

[html] view
plain
copy

  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>

[html] view
plain
copy

  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>
时间: 2024-11-07 14:29:32

ScheduledExecutorService定时周期运行指定的任务的相关文章

ScheduledExecutorService定时周期执行指定的任务

示例代码 package com.effective.common.concurrent.execute; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.Executors; import java.util.concurrent.Scheduled

android ScheduleExecutorService定时周期执行指定任务

一:简单说明 ScheduleExecutorService接口中有四个重要的方法,其中scheduleAtFixedRate和scheduleWithFixedDelay在实现定时程序时比较方便. 下面是该接口的原型定义 java.util.concurrent.ScheduleExecutorService extends ExecutorService extends Executor 接口scheduleAtFixedRate原型定义及参数说明 [java] view plaincopy

Java 定时循环运行程序

Timer 和 ScheduledExecutorSeruvce 都能执行定时的循环任务,有函数 scheduleAtFixedRate.但是,如果任务运行时间较长,超过了一个周期时长,下一个任务就会被延缓执行. 例如代码: public class ScheduledRunnableTest extends TimerTask { public void run() { try { Thread.sleep(2000); System.out.println(new Timestamp(Sys

java ScheduleExecutorService 定时周期执行任务

ScheduleExecutorService接口 int poolSize = 500;//定义线程调度池 ScheduledExecutorService execSrv = Executors.newScheduledThreadPool(poolSize); //启用线程调度 ChildThread childThread = new AlarmChildThread(1, ruleList); int period = 30;//调用周期 long initialDelay = 60;

spring 基于quartz框架实现定时周期执行

Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度.本系统结合通过 Spring 来集成 Quartz . 别忘了spring中的jar包哦 quartz-all.zip 项目中使用到 在网上收集整理了一番 package com.task.quartz; import java.text.SimpleDateFormat; import java.u

结合Django+celery二次开发定时周期任务

需求: 前端时间由于开发新上线一大批系统,上完之后没有配套的报表系统.监控,于是乎开发.测试.产品.运营.业务部.财务等等各个部门就跟那饥渴的饿狼一样需要 各种各样的系统数据满足他们.刚开始一天一个还能满足他们,优化脚本之后只要开发提供查询数据的SQL.收件人.执行时间等等参数就可以几分钟写完一个定时任务脚本 ,到后面不知道是不是吃药了一天三四个定时任务,不到半个月手里一下就20多个定时任务了,渐渐感到力不从心了,而且天天还要给他们修改定时任务的SQL.收件人.执 行时间等等,天天写定时任务脚本

Junit4.x扩展:运行指定方法

相信很多道友搞开发的一般都会用到Junit单元测试工具,不知道大家有没有遇到一个这样的问题: 有的单元测试用例有很多@Test方法,甚至有的方法会执行很长时间,只能空等执行.而实际上我们只需要运行其中的某一些方法就可以了.然后有人会说不是有ingore注解么,可ingore需要为许多的方法添加,当测试方法达到一定数量级的时候,改起来会很烦躁,如果commit到代码服务器上甚至可能会影响别人工作.己所不欲... 之前有朋友跟我说过TestNG是支持指定执行哪些方法,本人没有亲自去实验,因为公司统一

聊一聊Vue实例与生命周期运行机制

Vue的实例是Vue框架的入口,担任MVVM中的ViewModel角色,所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数可以实现组件数据管理和DOM渲染两大重要功能.例如,实例需要配置数据观测(data observer).编译模版.挂载实例到 DOM ,然后在数据变化时更新 DOM .在这个过程中,事件钩子可以辅助我们对整个实例生成.编译.挂载.销毁等过程进行js控制,给我们提供了执行自定义逻辑的机会.所以学习实例的生命周期,能帮助我们理解vue实例的运行机制,更

Runas命令:能让域用户/普通User用户以管理员身份运行指定程序。

注:本文由Colin撰写,版权所有!转载请注明原文地址,谢谢合作! 在某些情况下,为了安全起见,大部分公司都会使用域控制器或只会给员工电脑user的用户权限,这样做能大大提高安全性和可控性,但由此也带来了一些困扰. 比如:某些特定的部门(如财务,物流)没有管理员权限,但工作又需要使用特定的插件或程序,且该程序或插件又必须以管理员身份运行,在这种情况下,我们如果将用户的权限提升为管理员,那样会增加安全风险而且可能引起很多不可控的情况.在这种情况下,我们可以使用runas命令来指定运行某个程序,这个