`
topzhujia
  • 浏览: 54382 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

在 Java 应用程序中定时执行任务

    博客分类:
  • JAVA
阅读更多

Java 中Timer 类的简洁用法

所有类型的 Java 应用程序一般都需要计划重复执行的任务。企业应用程序需要计划每日的日志或者晚间批处理过程。一个 J2SE或者 J2ME 日历应用程序需要根据用户的约定计划闹铃时间。不过,标准的调度类 Timer 和 TimerTask 没有足够的灵活性,无法支持通常需要的计划任务类型。在本文中,Java 开发人员 Tom White 向您展示了如何构建一个简单通用的计划框架,以用于执行任意复杂的计划任务。
我将把 java.util.Timer 和 java.util.TimerTask 统称为 Java 计时器框架,它们使程序员可以很容易地计划简单的任务(注意这些类也可用于 J2ME 中)。在 Java 2 SDK, Standard Edition, Version 1.3 中引入这个框架之前,开发人员必须编写自己的调度程序,这需要花费很大精力来处理线程和复杂的 Object.wait() 方法。不过,Java 计时器框架没有足够的能力来满足许多应用程序的计划要求。甚至一项需要在每天同一时间重复执行的任务,也不能直接使用 Timer 来计划,因为在夏令时开始和结束时会出现时间跳跃。

本文展示了一个通用的 Timer 和 TimerTask 计划框架,从而允许更灵活的计划任务。这个框架非常简单 ―― 它包括两个类和一个接口 ―― 并且容易掌握。如果您习惯于使用 Java 定时器框架,那么您应该可以很快地掌握这个计划框架(有关 Java 定时器框架的更多信息,请参阅 参考资料)。

计划单次任务
计划框架建立在 Java 定时器框架类的基础之上。因此,在解释如何使用计划框架以及如何实现它之前,我们将首先看看如何用这些类进行计划。

想像一个煮蛋计时器,在数分钟之后(这时蛋煮好了)它会发出声音提醒您。清单 1 中的代码构成了一个简单的煮蛋计时器的基本结构,它用 Java 语言编写:

清单 1. EggTimer 类

 1package org.tiling.scheduling.examples; 
 2

 3import
 java.util.Timer; 
 4import
 java.util.TimerTask; 
 5

 6public class EggTimer 

 7     private final Timer timer = new
 Timer(); 
 8     private final int
 minutes; 
 9

10     public EggTimer(int minutes) 

11         this.minutes =
 minutes; 
12     }
 
13

14     public void start() 

15         timer.schedule(new TimerTask() 

16             public void run() 

17
                 playSound(); 
18
                 timer.cancel(); 
19             }
 
20             private void playSound() 

21                 System.out.println("Your egg is ready!"
); 
22                 // Start a new thread to play a sound 

23             }
 
24         }
, minutes * 60 * 1000); 
25     }
 
26

27     public static void main(String[] args) 

28         EggTimer eggTimer = new EggTimer(2
); 
29
         eggTimer.start(); 
30     }
 
31

32}
 
33




EggTimer 实例拥有一个 Timer 实例,用于提供必要的计划。用 start() 方法启动煮蛋计时器后,它就计划了一个 TimerTask ,在指定的分钟数之后执行。时间到了, Timer 就在后台调用 TimerTask 的 start() 方法,这会使它发出声音。在取消计时器后这个应用程序就会中止。

计划重复执行的任务
通过指定一个固定的执行频率或者固定的执行时间间隔, Timer 可以对重复执行的任务进行计划。不过,有许多应用程序要求更复杂的计划。例如,每天清晨在同一时间发出叫醒铃声的闹钟不能简单地使用固定的计划频率 86400000 毫秒(24 小时),因为在钟拨快或者拨慢(如果您的时区使用夏令时)的那些天里,叫醒可能过晚或者过早。解决方案是使用日历算法计算每日事件下一次计划发生的时间。而这正是计划框架所支持的。考虑清单 2 中的 AlarmClock 实现(有关计划框架的源代码以及包含这个框架和例子的 JAR 文件,请参阅 参考资料):

清单 2. AlarmClock 类

 1package org.tiling.scheduling.examples; 
 2

 3import
 java.text.SimpleDateFormat; 
 4

 5import
 java.util.Date; 
 6

 7import
 org.tiling.scheduling.Scheduler; 
 8import
 org.tiling.scheduling.SchedulerTask; 
 9import
 org.tiling.scheduling.examples.iterators.DailyIterator; 
10

11public class AlarmClock 

12

13     private final Scheduler scheduler = new
 Scheduler(); 
14     private final SimpleDateFormat dateFormat =
 
15         new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS"
); 
16     private final int
 hourOfDay, minute, second; 
17

18     public AlarmClock(int hourOfDay, int minute, int second) 

19         this.hourOfDay =
 hourOfDay; 
20         this.minute =
 minute; 
21         this.second =
 second; 
22     }
 
23

24     public void start() 

25         scheduler.schedule(new SchedulerTask() 

26             public void run() 

27
                 soundAlarm(); 
28             }
 
29             private void soundAlarm() 

30                 System.out.println("Wake up! " +
 
31                     "It's " + dateFormat.format(new
 Date())); 
32                 // Start a new thread to sound an alarm 

33             }
 
34         }
new DailyIterator(hourOfDay, minute, second)); 
35     }
 
36

37     public static void main(String[] args) 

38         AlarmClock alarmClock = new AlarmClock(700
); 
39
         alarmClock.start(); 
40     }
 
41}
 
42

43



注意这段代码与煮蛋计时器应用程序非常相似。 AlarmClock 实例拥有一个 Scheduler (而不是 Timer )实例,用于提供必要的计划。启动后,这个闹钟对 SchedulerTask (而不是 TimerTask )进行调度用以发出报警声。这个闹钟不是计划一个任务在固定的延迟时间后执行,而是用 DailyIterator 类描述其计划。在这里,它只是计划任务在每天上午 7:00 执行。下面是一个正常运行情况下的输出:


Wake up! It's 24 Aug 2003 07:00:00.023
Wake up! It's 25 Aug 2003 07:00:00.001
Wake up! It's 26 Aug 2003 07:00:00.058
Wake up! It's 27 Aug 2003 07:00:00.015
Wake up! It's 28 Aug 2003 07:00:00.002
...



DailyIterator 实现了 ScheduleIterator ,这是一个将 SchedulerTask 的计划执行时间指定为一系列 java.util.Date 对象的接口。然后 next() 方法按时间先后顺序迭代 Date 对象。返回值 null 会使任务取消(即它再也不会运行)―― 这样的话,试图再次计划将会抛出一个异常。清单 3 包含 ScheduleIterator 接口:

清单 3. ScheduleIterator 接口

1package org.tiling.scheduling; 
2

3import
 java.util.Date; 
4

5public interface ScheduleIterator 

6     public
 Date next(); 
7}
 






DailyIterator 的 next() 方法返回表示每天同一时间(上午 7:00)的 Date 对象,如清单 4 所示。所以,如果对新构建的 next() 类调用 next() ,那么将会得到传递给构造函数的那个日期当天或者后面一天的 7:00 AM。再次调用 next() 会返回后一天的 7:00 AM,如此重复。为了实现这种行为, DailyIterator 使用了 java.util.Calendar 实例。构造函数会在日历中加上一天,对日历的这种设置使得第一次调用 next() 会返回正确的 Date 。注意代码没有明确地提到夏令时修正,因为 Calendar 实现(在本例中是 GregorianCalendar )负责对此进行处理,所以不需要这样做。

清单 4. DailyIterator 类

 1package org.tiling.scheduling.examples.iterators; 
 2

 3import
 org.tiling.scheduling.ScheduleIterator; 
 4

 5import
 java.util.Calendar; 
 6import
 java.util.Date; 
 7

 8/** */
/** 
 9
* A DailyIterator class returns a sequence of dates on subsequent days 
10
* representing the same time each day. 
11*/
 
12public class DailyIterator implements ScheduleIterator 

13     private final int
 hourOfDay, minute, second; 
14     private final Calendar calendar =
 Calendar.getInstance(); 
15

16     public DailyIterator(int hourOfDay, int minute, int second) 

17         this(hourOfDay, minute, second, new
 Date()); 
18     }
 
19

20     public DailyIterator(int hourOfDay, int minute, int second, Date date) 

21         this.hourOfDay =
 hourOfDay; 
22         this.minute =
 minute; 
23         this.second =
 second; 
24
         calendar.setTime(date); 
25
         calendar.set(Calendar.HOUR_OF_DAY, hourOfDay); 
26
         calendar.set(Calendar.MINUTE, minute); 
27
         calendar.set(Calendar.SECOND, second); 
28         calendar.set(Calendar.MILLISECOND, 0
); 
29         if (!calendar.getTime().before(date)) 

30             calendar.add(Calendar.DATE, -1
); 
31         }
 
32     }
 
33

34     public Date next() 

35         calendar.add(Calendar.DATE, 1
); 
36         return
 calendar.getTime(); 
37     }
 
38

39}
 
40</s
分享到:
评论

相关推荐

    在 Java 应用程序中定时执行任务.doc

    所有类型的 Java 应用程序一般都需要计划重复执行的任务。企业应用程序需要计划每日的日志或者晚间批处理过程。一个 J2SE 或者 J2ME 日历应用程序需要根据用户的约定计划闹铃时间。不过,标准的调度类 Timer 和 ...

    Java 应用程序中定时执行任务的定时器框架

    所有类型的 Java 应用程序一般都需要计划重复执行的任务。企业应用程序需要计划每日的日志或者晚间批处理过程。一个 J2SE或者 J2ME 日历应用程序需要根据用户的约定计划闹铃时间。不过,标准的调度类 Timer 和 ...

    spring整合java quartz实现动态定时任务的前台网页配置与管理

    在实际项目应用中经常会用到定时任务,可以通过quartz和spring的简单配置即可完成,但如果要改变任务的执行时间、频率,废弃任务等就需要改变配置甚至代码需要重启服务器,这里介绍一下如何通过quartz与spring的组合...

    java定时执行sql语句

    使用jfinal编写的本地应用,压缩文件里包括了eclipse本程序的源代码和可执行的jar文件。 通过配置数据库连接信息和要执行的sql语句,可实现定时执行多个sql语句。 所要执行的语句只能是写死的,可支持sqlserver ...

    java 定时执行任务 定时关机 定时重启

    使用Java Swing写的一个小程序,用来定时关机、定时重启、定时执行某一个应用程序。执行时调用cmd命令执行的。其他的,就没什么了,最后用exe4j把jar打包成了exe文件,在本地测能用,不知道其他地方是否能用,内部有...

    org.tiling.scheduling

    在 Java 应用程序中定时执行任务 IBM里下载的

    使用Java创建任务调度器 - 一个实战教程

    在这个实战博客中,我们将创建一个Java任务调度器,演示如何使用Java编程语言和任务调度库来计划和执行定时任务。 以下是本实战博客的主要内容: 项目概述 准备工作 创建Java项目 添加任务调度库 设计任务 实现...

    定时多任务通知器1.0

    当你有很多事情需要提醒的时候,或者有很多重复的工作要做,定时通知器可以帮你很大的忙哦!目前版本的功能有: ...2. 定时运行应用程序 3. 定时天气预报 4. 定时关闭计算机 5. 定时模拟鼠标键盘 6. 定时更改桌面背景

    java定时器的使用

    在应用开发中,经常需要一些周期性的操作,比如每5分钟执行某一操作等。 对于这样的操作最方便、高效的实现方式就是使用java.util.Timer工具类。

    Java 7并发编程实战手册

    java7在并发编程方面,带来了很多令人激动的新功能,这将使你的应用程序具备更好的并行任务性能。 《Java 7并发编程实战手册》是Java 7并发编程的实战指南,介绍了Java 7并发API中大部分重要而有用的机制。全书分为9...

    Java并发编程(学习笔记).xmind

    某些应用程序中存在比较明显的任务边界,而在其他一些程序中则需要进一步分析才能揭示出粒度更细的并行性 任务的取消和关闭 任务取消 停止基于线程的服务 处理非正常的线程终止 JVM关闭 线程池...

    java课程设计:日历记事本

    编写一个Applet小应用程序能够显示时间,当用户最小化Applet时,程序会 被挂起,当还原Applet时,程序又会恢复执行,同时Applet中应显示挂起和恢复的时间。 (二)系统要求: 1、要求利用面向对象的方法以及Java的...

    termux-boot:Termux附加应用程序,允许程序在启动时运行

    附加应用程序,可在启动时运行程序。 在开发(或打包)时,请注意,此应用程序需要使用与Termux主应用程序相同的密钥签名,才能获得执行脚本的权限。 安装 Termux:Boot应用程序可以从获得。 此外,我们为那些想...

    Java版水果管理系统源码-task-scheduler:任务调度器

    Java版水果管理系统源码 任务调度系统介绍 简介 任务调度系统目的是对spring boot类型的java项目的cron类型...Executor是执行器,集成在每一个执行节点上,用来接收来自调度器的任务,并调用应用程序的对应方法执行,在

    Java开发技术大全(500个源代码).

    HelloWorldApp.java 第一个用Java开发的应用程序。 firstApplet.java 第一个用Java开发的Applet小程序。 firstApplet.htm 用来装载Applet的网页文件 第2章 示例描述:本章介绍开发Java的基础语法知识。 ...

    Quartz调度框架预研.docx

    Quartz完全使用Java开发,可以集成到各种规模的应用程序中。它能够承载成千上万的任务调度,并且支持集群。它支持将数据存储到数据库中以实现持久化,并支持绝大多数的数据库。它将任务与触发设计为松耦合,即一个...

    一个轻量级权限管理系统,包含:管理员管理、角色管理、菜单管理、定时任务、参数管理、代码生成器等.zip

    跨平台性(Write Once, Run Anywhere): Java的代码可以在不同的平台上运行,只需编写一次代码,就可以在任何支持Java的设备上执行。这得益于Java虚拟机(JVM),它充当了代码和底层硬件之间的中介。 面向对象: ...

    linux项目工程资料-基于java,python爬虫、linux定时任务的易班自动签到系统基础框架.zip

    该项目以Linux内核为核心,围绕其构建了一个完整的操作系统,包括各种系统工具、库、应用程序和硬件支持。 以下是Linux项目的一些主要特点和资料介绍: 开放源代码:Linux项目的所有源代码都是公开的,并允许任何...

    若依通用权限管理系统接口文档,是一个 Java EE 企业级快速开发平台,基于经典技术组合(Spring Boot、Spring

    在主程序执行main函数就可以运行。你也可以打包你的应用为jar并通过使用java -jar来运行你的Web应用。它遵循"约定优先于配置"的原则, 使用SpringBoot只需很少的配置,大部分的时候直接使用默认的配置即可。同时...

    Java并发编程实战

    6.1 在线程中执行任务93 6.1.1 串行地执行任务94 6.1.2 显式地为任务创建线程94 6.1.3 无限制创建线程的不足95 6.2 Executor框架96 6.2.1 示例:基于Executor的Web服务器97 6.2.2 执行策略98 6.2.3 线程池98...

Global site tag (gtag.js) - Google Analytics