任务调度(二)——jdk自带的Timer 动态修改任务执行计划_timetask移除任务重新设置任务_龙轩的博客-程序员秘密

技术标签: 【java基础】  Timer 任务调度  

       上一篇博文《任务调度(一)——jdk自带的Timer》中,简单介绍了一下Timer,本文将分享一下如何动态修改Timer制定的计划。


       先上代码:

package com.tgb.ccl.schema.dynamic;

import java.util.Date;

/** 
 * 可动态修改的任务
 * 
 * @author arron
 * @date 2015年5月9日 下午1:52:15 
 * @version 1.0 
 */
public class DynamicTimerTask extends  java.util.TimerTask {

	@Override
	public void run() {
		System.out.println("---------start--------");
		Date d = new Date();
		for(int i=0;i<2;i++){
			try {
				Thread.sleep(1000);
				System.out.println("已执行【"+(i+1)+"】秒钟,at: "+d.toLocaleString());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("本次任务调度结束,at: "+new Date().toLocaleString());
		System.out.println("----------------------------------------------");
	}
}
package com.tgb.ccl.schema.dynamic;

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;

/**
 * 任务调度管理器
 * 
 * @author arron
 * @date 2015年5月9日 下午1:57:19
 * @version 1.0
 */
public class DynamicTaskManager {
	private static final long PERIOD = 5 * 1000;// 5秒钟
	
	/**
	 * 单例对象
	 */
	private static DynamicTaskManager taskManager = null;	
	
	/**
	 * 时间调度对象
	 */
	private static Timer timer = new Timer();
	
	/**
	 * 任务
	 */
	private static DynamicTimerTask task = null;

	static {
		taskManager = new DynamicTaskManager();
	}
	
	public static DynamicTaskManager getInstance(){
		if(taskManager==null){
			taskManager = new DynamicTaskManager();
		}
		return taskManager;
	}

	public DynamicTaskManager() {
	}

	@SuppressWarnings("deprecation")
	public void startTask(Date startTime, long period){
		
		System.out.println("设置启动时间: "+startTime.toLocaleString());
		//如果当前时间超过了设定时间,会立即执行一次
		task = new DynamicTimerTask();
		timer.schedule(task, startTime,period);
		
	}
	

	/**
	 * 启动定时器
	 */
	public void start() {
		//启动任务,10点40启动任务
		start(DateUtils.bookTime(10,40,0));
	}
	
	/**
	 * 启动定时器
	 */
	public void start(long preiod) {
		//启动任务,10点40启动任务
		start(DateUtils.bookTime(10,40,0),preiod);
	}
	
	/**
	 * 启动定时器
	 */
	public void start(Date startTime) {
		start(startTime,PERIOD);
	}
	
	/**
	 * 启动定时器
	 */
	public void start(Date startTime,long preiod) {
		startTask(startTime,preiod);
	}
	
	/**
	 * 重新启动
	 */
	public void restart() {
		clean();
		start();
	}

	/**
	 * 清空timer
	 */
	public void clean() {
		if(task != null){
			task.cancel();
		}
		timer.purge();
	}
	
	/**
	 * 停止任务
	 */
	public void stop(){
		System.out.println("--------任务正在停止---------");
		clean();	
		System.out.println("---------任务已停止----------");
	}
	
	static class DateUtils{
		/**
		 * 增加或减少天数
		 * 
		 * @param date
		 * @param CalendarFlag  
		 * 				取值 Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY,
		 * 					   Calendar.MINUTE,Calendar.SECOND,Calendar.MILLISECOND
		 * @param num
		 * @return
		 */
		public static Date addDay(Date date, int CalendarFlag, int num) {
			Calendar startDT = Calendar.getInstance();
			startDT.setTime(date);
			startDT.add(CalendarFlag, num);
			return startDT.getTime();
		}
		
		/**
		 * 设定时间
		 * 
		 * @param hour
		 * @param minute
		 * @param second
		 * @return
		 */
		public static Date bookTime(int hour, int minute, int second) {
			Calendar calendar = Calendar.getInstance();
			calendar.set(Calendar.HOUR_OF_DAY, hour);
			calendar.set(Calendar.MINUTE, minute);
			calendar.set(Calendar.SECOND, second);
			Date date = calendar.getTime();
			return date;
		}
	}
	
	
	@SuppressWarnings("deprecation")
	public static void main(String[] args) {
		DynamicTaskManager manager = DynamicTaskManager.getInstance();
		//启动任务,会立即执行一次,2s时执行完毕,5s时第二次执行,7s时第二次执行完毕
		manager.start();
		
		for(int i=0;i<8;i++){
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		//8s时,stop原任务,动态更改启动时间
		manager.stop();
		System.out.println("当前时间:"+new Date().toLocaleString());
		
		System.out.println("修改原计划,5s后重新执行");
		//5s后再启动,即13s时再启动
		manager.start(DateUtils.addDay(new Date(), Calendar.SECOND, 5));
	}
}

       运行结果如下:


       从结果中,我们可以看到,原先的计划是在14:46:40时开始,第二次是在14:46:45,每次执行2s中,也就是说如果不更改任务计划,那么任务将总会在0s或者5s的时候执行。但是我在main方法中,将原来的任务关闭,然后修改了启动时间,当前时间5s后启动新任务。当前时间为14:46:48,5s后执行了新计划。这就完成了任务的动态修改。


       首先说一下,如果关闭任务,stop方法完成了这个功能。要想任务不继续执行,必须将task的状态设置为cancel,然后调用timer的purge方法,将队列里的所有状态为cancel的task移除。这样就算到了执行时间,由于task已经移除,也就不会再执行了。如果使用了timer的cancel()方法,那么会将timer中所有的task全部移除掉。这点要注意一下。


       其实在项目中使用时,要比这个还要简单。直接修改startTask()方法,启动时间和间隔都是从数据库中取就ok了。只要想更改计划时,先配置好启动时间和间隔,然后自己写一个restart的方法,调用clean和startTask方法即可。


       有人问我Timer和Quartz框架的区别。那我就说一下我的理解。Timer毕竟是jdk自带的简易的任务调度工具类,跟Quartz比肯定是鸟枪与大炮的差距。Quartz的配置规则更加强大,更能满足我们的复杂需求,还允许多线程,这是Timer所比不了的。如果你就需要特别简单的任务调度,那么我觉得完全没有必要用Quartz。杀鸡焉用牛刀?!如果你的业务场景比较复杂,比如要求每个月的第4周的最后一个工作日要执行结算工资,如果最后一天是周六,就会向前提一天,在周五执行。这样的场景用Quartz要比Timer简单吧。


       不过具体用什么,还需要看项目。没有什么谁更牛,只有谁更适合。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xiaoxian8023/article/details/45601347

智能推荐

(适用于主机连接WiFi的情况)解决vmware workstation的Ubuntu虚拟机无法联网的问题_邪三一的博客-程序员秘密

背景介绍:主机用的是WiFi,虚拟机的Ubuntu是用的以太网,并且设置的是静态ip,VM网络配置的是自定义。平时主机可以在关闭WiFi且连接网线的情况下ping通虚拟机。综上情况,我想让Ubuntu也能上网,于是搜索相关解决方案,在结合网上大佬们的方案后我摸索出一个解决方案,方案如下:第一步打开VM的可移动设备,再选择网络适配器,再选择设置。第二步选择网络连接为自定义,选择VMnet...

eclipse的svn提交时如果断网,选择取消后等待时间太长、卡住,解决办法_svn http-timeout_拉比小猪的博客-程序员秘密

eclipse的svn提交时如果断网,选择取消后等待时间太长,怎么解决?使用Eclipse通过VPN连接到SVN。有时VPN连接断开,忘记重连VPN就提交时,必须等待10分钟直到超时。等待时间太长怎么办?解决办法:修改SVN连接超时的时间。具体修改servers文件如下C:\用户\用户名\AppData\Roaming\Subversion\servers我的路径是:C:\Users\xxx\AppData\Roaming\Subversion\servers记事本打开servers搜索[gl

python+opencv学习笔记_道人兄的博客-程序员秘密

图片打开以及视频帧保存读取的经验记录

VB.net学习笔记(二十七)线程同步上_vbnet线程同步_dzweather的博客-程序员秘密

X夫妇二人试图同时从同一账户(总额1000)中支取1000。由于余额有1000,夫妇各自都满足条件,于是银行共支付2000。结果是银行亏了1000元。这种两个或更多线程试图在同一时刻访问同一资源来修改其状态,并产生不良后果的情况被称做竞争条件。                                                为避免竞争条件,需要使Withdraw()方法具有线

javaSE第六章——异常_疯子在辉的博客-程序员秘密

javaSE第六章——异常文章目录javaSE第六章——异常java异常概念异常的体系异常处理trycatchfinallythrowsthrowthrows和throw自定义异常java异常概念在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的,比如:客户输入数据的格式,读取文件是否存在,网络是否始终保持通畅等等。异常:在java语言中,将程序执行中发生的不正常情况称为“异常”。java程序在执行过程中

随便推点

【开发利器】中国国内可用API合集_Yort的博客-程序员秘密

中国国内可用API合集笔记OneNote - OneNote支持获取,复制,创建,更新,导入与导出笔记,支持为笔记添加多媒体内容,管理权限等。提供SDK和Demo。 为知笔记 - 为知笔记Windows客户端开放了大量的API,其中绝大部分,都通过COM提供,可以在javascript, C#, C++, Delphi等语言中使用。接口通过IDL(Interface description lan

实验2-2 单源最短路算法Dijkstra_dijkstra算法实验_LLoadin的博客-程序员秘密

问题如果从图中某一顶点到达另一顶点的路径可能不止一条,如何找到一条路径使得沿此路径上各边的权值总和(称为路径长度)达到最小。可以将适用最短路的算法分为单源最短路和多源最短路。解析单源最短路算法Dijkstra对于下图使用Dijkstra算法求由顶点a到顶点h的最短路径每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径。即从剩余路径中找最短的路径...

数字图像处理|Matlab-基于颜色的车牌识别程序_匿名用户小易的博客-程序员秘密

Matlab-车牌识别⻋牌自动识别技术的关键在于⻋牌定位、字符切割、字符识别及后续处理等Hough变换的方法在⻋牌区域变形或图象被污损情况下容易失效灰度分割则比直线检测的方法要稳定,但当图象在有许多与⻋牌的灰度非常相似的区域时,该方法也容易失效纹理分析在遇到类似⻋牌纹理特征的其他因素干扰时,⻋牌定位正确率也会受到影响过程&amp;结果????Matlab代码????main.m????cl...

java中file文件的操作_骑士李四的博客-程序员秘密

骑士李四记录在java中对文件的操作也是很重要的一块,我们这里来复习总结一下文件操作的基本使用1.提纲:1.文件的创建2.文件的删除3.文件的查看4.文件的获取5.文件的读写2.代码:package com.pengli.programutils.utils.javabase;import java.io.*;/** * @Description: 文件的操作 * @Author: pengli * @CreateDate: 2020/5/24 10:31 */publi

python读取dat数据,从python中的.dat文件读取和做计算_第四张牌的博客-程序员秘密

I need to read a .dat file in python which has 12 columns in total and millions of lines of rows. I need to divide column 2,3 and 4 with column 1 for my calculation. So before I load that .dat file, d...

android 进程/线程管理(三)----Thread,Looper / HandlerThread / IntentService_weixin_30405421的博客-程序员秘密

Thread,Looper的组合是非常常见的组合方式。Looper可以是和线程绑定的,或者是main looper的一个引用。下面看看具体app层的使用。首先定义thread:package com.joyfulmath.androidstudy.thread;import com.joyfulmath.androidstudy.TraceLog;import ...

推荐文章

热门文章

相关标签