Java 定时任务系列(1)- Java原生支持
来源:互联网 发布:博客推荐知乎 编辑:程序博客网 时间:2024/05/07 21:24
1、普通thread实现
这是最常见的,创建一个thread,然后让它在while循环里一直运行着,通过sleep方法来达到定时任务的效果。这样可以快速简单的实现,代码如下:
public class Task1 {public static void main(String[] args) { // run in a second final long timeInterval = 1000; Runnable runnable = new Runnable() { public void run() { while (true) { // ------- code for task to run System.out.println("Hello !!"); // ------- ends here try { Thread.sleep(timeInterval); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread thread = new Thread(runnable); thread.start(); }}
2、用Timer和TimerTask
java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks。
一个java.util.TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类的方式创建。
用Timer和TimerTask的话与上述方法相比有如下好处:
当启动和去取消任务时可以控制
第一次执行任务时可以指定你想要的delay时间
在实现时,Timer类可以调度任务,TimerTask则是通过在run()方法里实现具体任务。
Timer实例可以调度多任务,它是线程安全的。
当Timer的构造器被调用时,它创建了一个线程,这个线程可以用来调度任务。
下面是代码:
Timer 测试类代码:
//import java.util.Date;import java.util.Timer;//import com.baibutao.apps.linkshop.uxiang.server.util.DateUtil;public class TestTimerTask {public static void main(String[] args){TaskA taskA = new TaskA();Timer timer = new Timer();timer.schedule(taskA, 5 * 1000, 5 * 1000);//Date date = DateUtil.parse("2014-12-04 16:50:00");//timer.schedule(taskA, date , 5 * 1000);//timer.scheduleAtFixedRate(taskA, date, 5 * 1000);}}
任务类代码:
import java.util.Date;import java.util.TimerTask;import wint.lang.utils.DateUtil;// 定义一个任务类public class TaskA extends TimerTask{@Overridepublic void run() {System.out.println(DateUtil.formatFullDate(new Date()));}}
关于Timer类的调用方法:
void java.util.Timer.schedule(TimerTask task, long delay):多长时间(毫秒)后执行任务
void java.util.Timer.schedule(TimerTask task, Date time):设定某个时间执行任务
void java.util.Timer.schedule(TimerTask task, long delay, long period):delay时间后开始执行任务,并每隔period时间调用任务一次。
void java.util.Timer.schedule(TimerTask task, Date firstTime, long period):第一次在指定firstTime时间点执行任务,之后每隔period时间调用任务一次。
void java.util.Timer.scheduleAtFixedRate(TimerTask task, long delay, long period):delay时间后开始执行任务,并每隔period时间调用任务一次。
void java.util.Timer.scheduleAtFixedRate(TimerTask task, long delay, long period):第一次在指定firstTime时间点执行任务,之后每隔period时间调用任务一次。
void java.util.Timer.cancel():终止该Timer
boolean java.util.TimerTask.cancel():终止该TimerTask
可以为每个Timer指定多个TimerTask
虽然可通过void java.util.Timer.schedule(TimerTask task, Date firstTime, long period)方法完成“例如:每天上午10点执行一次”的业务,但该实现是基于进行一天(1000 * 60 * 60 * 24毫秒)进行延迟的机制实现的,并不是指定某个具体时间进行执行的。
对于该种需求,可通过Quartz来进行实现
方法名称schedule()和scheduleAtFixedRate()两者的区别
当需要根据period区间时间循环多次调用任务的时候,会存在两种不同的策略,两种方法提供了不同的策略。
调用方法(1)、(2)只是单次执行,不存在多次调用任务的情况,所以没有提供scheduleAtFixedRate方法的调用方式。
<1>schedule()方法更注重保持间隔时间的稳定:保障每隔period时间可调用一次
<2>scheduleAtFixedRate()方法更注重保持执行频率的稳定:保障多次调用的频率趋近于period时间,如果某一次调用时间大于period,下一次就会尽量小于period,以保障频率接近于period
3、ScheduledExecutorService
ScheduledExecutorService是从Java SE 5的java.util.concurrent里,做为并发工具类被引进的,这是最理想的定时任务实现方式。相比于上两个方法,它有以下好处:
相比于Timer的单线程,它是通过线程池的方式来执行任务的
可以很灵活的去设定第一次执行任务delay时间
提供了良好的约定,以便设定执行的时间间隔
下面是实现代码,我们通过ScheduledExecutorService#scheduleAtFixedRate展示这个例子,通过代码里参数的控制,首次执行加了delay时间。
import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class Task3 { public static void main(String[] args) { Runnable runnable = new Runnable() { public void run() { // task to run goes here System.out.println("Hello !!"); } }; ScheduledExecutorService service = Executors .newSingleThreadScheduledExecutor(); service.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.SECONDS); }}
关于ScheduledExecutorService 的具体用法,请参照涛涛的博客
4、web容器中利用ServletContextListener实现定时任务
package com.ed.cnc.servletListener;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import com.ed.cnc.city.StatisticsTask;/** * 统计ContextListener * @author westd * *//** * @author westd * */public class StatisticsContextListener implements ServletContextListener{ private java.util.Timer timer = null; /** * 这个方法在Web应用服务做好接受请求的时候被调用。 * * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) */ public void contextInitialized(ServletContextEvent event) { timer = new java.util.Timer(true); event.getServletContext().log("定时器已启动"); timer.schedule(new StatisticsTask(event.getServletContext()), 0, 60*60*1000);//每隔1小时 event.getServletContext().log("已经添加任务调度表"); } /** * 这个方法在Web应用服务被移除,没有能力再接受请求的时候被调用。 * * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) */ public void contextDestroyed(ServletContextEvent event) { timer.cancel(); event.getServletContext().log("定时器销毁"); }}
一个继承于TimerTask的一个类:StatisticsTask.java
package com.ed.cnc.city;import java.util.Calendar;import java.util.TimerTask;import javax.servlet.ServletContext;/** * 统计任务 * @author westd * */public class StatisticsTask extends TimerTask{ private static final int STATISTICS_SCHEDULE_HOUR = 0; private static boolean isRunning = false; private ServletContext context = null; public StatisticsTask(ServletContext context) { this.context = context; } @Override public void run() { Calendar cal = Calendar.getInstance(); //System.out.println(isRunning); if (!isRunning) { if (STATISTICS_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) //查看是否为凌晨 { isRunning = true; context.log("开始执行指定任务"); //TODO 添加自定义的详细任务 executeTask(); //指定任务执行结束 isRunning = false; context.log("指定任务执行结束"); } } else { context.log("上一次任务执行还未结束"); } } /** * 执行任务 */ public void executeTask() { System.out.println("任务1"); System.out.println("任务2"); }}web.xml中添加如下代码:
<listener> <listener-class>com.ed.cnc.servletListener.StatisticsContextListener</listener-class></listener>
- Java 定时任务系列(1)- Java原生支持
- Java定时任务(1)
- 定时任务(java)
- Java 定时任务系列(2)- Spring定时任务的几种实现
- java原生实现定时任务 与 Spring自带的定时任务
- java定时任务1:Timer
- 定时任务 java(实例)
- Java定时任务(2)
- java定时任务(三):timerTask定时任务
- JAVA定时执行任务(Tomcat 下的定时任务)
- java定时任务
- 定时任务实现 java
- java执行定时任务
- Java Web定时任务
- JAVA定时执行任务
- JAVA定时执行任务
- java定时任务
- Tomcat java 定时任务
- 感谢有你
- Oracle重建WMSYS用户
- Codeforces Round #280 (Div. 2)A B C
- angularjs1.3.0源码解析之service
- HttpClient release connection 该放手的时候必须放手
- Java 定时任务系列(1)- Java原生支持
- SQLite2MySQL 转换
- 小白学c++之 unix共享内存
- [500lines]500行代码写web server
- Java代理模式 静态代理 动态代理
- 给UITextView增加了链接
- 告别Spinner下拉列表,用popupWindow 更美好
- 黑马程序员——java基础之薄弱点总结(二)
- handler与Message使用