java用ScheduledThreadPoolExecutor实现定时任务比Timer稳定
1.ScheduledThreadPoolExecutor简介
java开始提供ScheduledThreadPoolExecutor类来支持周期性任务的调度,在这之前,这些工作需要依靠TimerTimerTask或者其它第三方工具来完成。但Timer有着不少缺陷,如Timer是单线程模式,调度多个周期性任务时,如果某个任务耗时较久就会影响其它任务的调度;如果某个任务出现异常而没有被catch则可能导致唯一的线程死掉而所有任务都不会再被调度。ScheduledThreadPoolExecutor解决了很多Timer存在的缺陷。
2.ScheduledThreadPoolExecutor和Timer比较
Timer对调度的支持是基于绝对时间的,因此任务对系统时间的改变是敏感的;而ScheduledThreadPoolExecutor支持相对时间。
·Timer使用单线程方式来执行所有的TimerTask,如果某个TimerTask很耗时则会影响到其他TimerTask的执行;而ScheduledThreadPoolExecutor则可以构造一个固定大小的线程池来执行任务。
·Timer不会捕获由TimerTask抛出的未检查异常,故当有异常抛出时,Timer会终止,导致未执行完的TimerTask不再执行,新的TimerTask也不能被调度;ScheduledThreadPoolExecutor对这个问题进行了妥善的处理,不会影响其他任务的执行。
3.ScheduledThreadPoolExecutor的主要方法:
3.1在指定的延迟后执行
<V>ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
3.2在指定的延迟后执行
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
3.3在指定的延迟后以固定速率执行(类似Timer.scheduleAtFixedRate())
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
3.4在指定的延迟后以固定间隔执行(类似Timer.schedule())
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
4.ScheduledThreadPoolExecutor定时任务案例(随tomcat启动的定时收短信的案例)
4.1.定时任务代码
/** * 执行定时任务 * @author Administrator * */ public class RepTaskScheduler implements Runnable{ private static final SMSManage smsManage=new SMSManage(); /** * 初始化定时器 */ public static void inist(){ ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(10); RepTaskScheduler initTiming = new RepTaskScheduler(); scheduler.scheduleAtFixedRate(initTiming,10,10,TimeUnit.SECONDS);10秒后启动,没隔10秒启动一次。 } /** * 这里写要定时执行的所有任务 */ @Override public void run() { //定时获取短信 smsManage.getSMS(); } }
4.2.随tomcat启动的servlet代码
public class InitServlet extends InitServletBase implements ServletContextListener { public void init(ServletContext servletContext) throws ServletException { super.init(servletContext); } public void contextInitialized(ServletContextEvent arg0) { try { init(arg0.getServletContext()); RepTaskScheduler.inist(); } catch (ServletException e) { System.out.println("初始化出错!"); } } public void contextDestroyed(ServletContextEvent arg0) { } }