- 浏览: 308399 次
- 性别:
- 来自: 武汉
最新评论
-
r463579217:
给一下代码demo呀
Java多线程总结之聊一聊Queue -
水土第一:
LZ 中间文章里面可能有单词拼写错误,小弟补一下。。。
pa ...
Java多线程总结之由synchronized说开去 -
xy_z487:
>> 回调函数:A调用B,同时传A给B。B执行完会 ...
深入浅出Java回调机制 -
xuxiaoyinliu:
THANKS 第一次遇到这种错误,原来是这样
String的valueOf方法传入null -
sinat_25176913:
赞赞赞,一直还在想为什么得到的是一个"null&qu ...
String的valueOf方法传入null
本文不是用来讲授入门手把手ABC小例子的,算是自己这段时间对Timer和Quartz使用心得的总结吧,后续如果有更深的认识会不断更新的。
言归正传,想实现定时调度,最简单的方法是使用Timer
还是先给个使用范例:
上面的代码实现了一个从当前时间开始执行的,以一分钟为周期的定时器。执行的内容在doSomething()方法中实现,这个方法返回是否继续执行的布尔值,因此可以在需要的时候将定时器cancel掉。
好了,让我们看一看Timer的源码。
(注:这个本人学习习惯有关,看了一个简单的例子就不想再看大段大段的文字了,还是看看源码比较直接,也比较准确)
Timer主要属性有以上两个,先来看看TimerThread,TimerThread是Timer的内部类,主要代码如下:
可以看到这代码不亏是出自大师手笔啊考虑的非常详细周到。
从这个代码可以看出,
(1)首先,TimerThread是个线程
(2)TimerThread自己维护了一个任务队列,也就是TaskQueue
(3)对队列的操作是线程安全的
(4)***处代码说明很重要的一点:如果前一个任务在执行完的时间已经超过了当前任务原定的开始时间,将当前任务的开始时间重新设置一个值然后执行。这同时也从侧面说明了,定时器的周期并不能结束正在执行的任务。
这话比较拗口,这样说吧,如果定时器的周期是1分钟,但是任务A执行时间是1分零十秒,当到达1分钟时,本来应该执行任务B,但是这时任务A还未执行完,这时会将任务A执行完,然后在1分钟零十秒的时候重新计算任务B的开始执行时间,设为2分钟时,那么任务B会在2分钟时开始执行。
在来看看TaskQueue,TaskQueue也是Timer的一个内部类:
通过源码可以看到TaskQueue其实就是在维护一个TimerTask[]。
那TimerTask又是什么呢?就是我们要定时的任务。部分源码如下:
我们所要做的第一步,就是实现一个TimerTask的对象。
然后所要做的就是,将这个对象作为参数传入Timer的schedule方法,请看源码:
再看看我们是如何使用Timer帮助我们实现定时调度的,我们可以发现Timer封装的很好,作为使用者可以不用关注TimerThread是如果对TaskQueue中的一个个TimerTask进行调度的。我们只需要创建一个定时任务然后交给TImer管理即可。但是了解了Timer的内部实现之后,使用起来就更加得心应手了。
------------------------------------我是分割线---------------------------------------
下面再来说说Quartz,Quartz提供了比Timer更加强大的时序调度功能。
关于Quartz,我不想说太多,原因在于:Quartz官方提供的15个例子太经典啦!!!还在网上找神马乱七八糟的例子啊,这15个例子看看自己跑跑试试,学起来又快又轻松!!!本文附件附送这些例子啊!!!
为了再降低一下看代码的门槛,这里提供一些关键的概念性的描述,有所了解或者不想看文字的朋友请略过。或者看代码有不懂的地方在来查看也可。
更详细的内容可以参考http://www.blogjava.net/baoyaer/articles/155645.html
在这列出再多例子都没有附件中的例子好,所以就不费口舌了。
言归正传,想实现定时调度,最简单的方法是使用Timer
还是先给个使用范例:
long PERIOD = 60*1000;//一分钟 Timer timer = new Timer("sure's timer"); timer.schedule(new TimerTask() { @Override public void run() { if(!doSomething()){ timer.cancel(); } } }, 0, PERIOD);
上面的代码实现了一个从当前时间开始执行的,以一分钟为周期的定时器。执行的内容在doSomething()方法中实现,这个方法返回是否继续执行的布尔值,因此可以在需要的时候将定时器cancel掉。
好了,让我们看一看Timer的源码。
(注:这个本人学习习惯有关,看了一个简单的例子就不想再看大段大段的文字了,还是看看源码比较直接,也比较准确)
public class Timer { private TaskQueue queue = new TaskQueue(); private TimerThread thread = new TimerThread(queue); }
Timer主要属性有以上两个,先来看看TimerThread,TimerThread是Timer的内部类,主要代码如下:
class TimerThread extends Thread { private TaskQueue queue;//任务队列 public void run() { try { mainLoop(); } finally { // Someone killed this Thread, behave as if Timer cancelled synchronized(queue) { newTasksMayBeScheduled = false; queue.clear(); } } } private void mainLoop() { while (true) { try { TimerTask task; boolean taskFired; synchronized(queue) { // 如果队列为空则等待 while (queue.isEmpty() && newTasksMayBeScheduled) queue.wait(); if (queue.isEmpty()) break; // 如果不再会非空,则跳出 // 队列非空,则取第一个任务执行 long currentTime, executionTime; task = queue.getMin();//取第一个任务 synchronized(task.lock) { if (task.state == TimerTask.CANCELLED) { queue.removeMin(); continue; // 任务已取消则继续取任务 } currentTime = System.currentTimeMillis();//当前时间 executionTime = task.nextExecutionTime;//任务将开始执行的时间 if (taskFired = (executionTime<=currentTime)) { if (task.period == 0) { queue.removeMin(); task.state = TimerTask.EXECUTED;//已执行完成 } else { //重复执行(***) queue.rescheduleMin( task.period<0 ? currentTime - task.period : executionTime + task.period); } } } if (!taskFired) // 还没到时间,则等到执行开始时间 queue.wait(executionTime - currentTime); } if (taskFired) // 执行 task.run(); } catch(InterruptedException e) { } } } }
可以看到这代码不亏是出自大师手笔啊考虑的非常详细周到。
从这个代码可以看出,
(1)首先,TimerThread是个线程
(2)TimerThread自己维护了一个任务队列,也就是TaskQueue
(3)对队列的操作是线程安全的
(4)***处代码说明很重要的一点:如果前一个任务在执行完的时间已经超过了当前任务原定的开始时间,将当前任务的开始时间重新设置一个值然后执行。这同时也从侧面说明了,定时器的周期并不能结束正在执行的任务。
这话比较拗口,这样说吧,如果定时器的周期是1分钟,但是任务A执行时间是1分零十秒,当到达1分钟时,本来应该执行任务B,但是这时任务A还未执行完,这时会将任务A执行完,然后在1分钟零十秒的时候重新计算任务B的开始执行时间,设为2分钟时,那么任务B会在2分钟时开始执行。
在来看看TaskQueue,TaskQueue也是Timer的一个内部类:
class TaskQueue { private TimerTask[] queue = new TimerTask[128]; ... }
通过源码可以看到TaskQueue其实就是在维护一个TimerTask[]。
那TimerTask又是什么呢?就是我们要定时的任务。部分源码如下:
public abstract class TimerTask implements Runnable { final Object lock = new Object();//锁 public abstract void run(); public boolean cancel() { synchronized(lock) { boolean result = (state == SCHEDULED); state = CANCELLED; return result; } } }
我们所要做的第一步,就是实现一个TimerTask的对象。
然后所要做的就是,将这个对象作为参数传入Timer的schedule方法,请看源码:
public void schedule(TimerTask task, long delay, long period) { if (delay < 0) throw new IllegalArgumentException("Negative delay."); if (period <= 0) throw new IllegalArgumentException("Non-positive period."); sched(task, System.currentTimeMillis()+delay, -period); } private void sched(TimerTask task, long time, long period) { if (time < 0) throw new IllegalArgumentException("Illegal execution time."); synchronized(queue) { if (!thread.newTasksMayBeScheduled) throw new IllegalStateException("Timer already cancelled."); synchronized(task.lock) { if (task.state != TimerTask.VIRGIN) throw new IllegalStateException( "Task already scheduled or cancelled"); task.nextExecutionTime = time;//设置该任务的开始时间 task.period = period;//设置该任务的周期 task.state = TimerTask.SCHEDULED;//将该任务的状态设为SCHEDULED } queue.add(task);//将该任务加入到任务队列中 if (queue.getMin() == task) queue.notify();//当列队的第一个任务是该任务时,唤醒 } }
再看看我们是如何使用Timer帮助我们实现定时调度的,我们可以发现Timer封装的很好,作为使用者可以不用关注TimerThread是如果对TaskQueue中的一个个TimerTask进行调度的。我们只需要创建一个定时任务然后交给TImer管理即可。但是了解了Timer的内部实现之后,使用起来就更加得心应手了。
------------------------------------我是分割线---------------------------------------
下面再来说说Quartz,Quartz提供了比Timer更加强大的时序调度功能。
关于Quartz,我不想说太多,原因在于:Quartz官方提供的15个例子太经典啦!!!还在网上找神马乱七八糟的例子啊,这15个例子看看自己跑跑试试,学起来又快又轻松!!!本文附件附送这些例子啊!!!
为了再降低一下看代码的门槛,这里提供一些关键的概念性的描述,有所了解或者不想看文字的朋友请略过。或者看代码有不懂的地方在来查看也可。
- Job:接口,只有一个方法void execute(JobExecutionContext context),开发者实现该接口定义Job所运行的任务,JobExecutionContext类提供了调度上下文的各种信息。Job运行时的信息保存在JobDataMap实例中。
- JobDetail:Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。通过该类的构造函数可以更具体地了解它的功用:JobDetail(java.lang.String name, java.lang.String group, java.lang.Class jobClass),该构造函数要求指定Job的实现类,以及任务在Scheduler中的组名和Job名称
- Trigger:是一个类,描述触发Job执行的时间触发规则。主要有SimpleTrigger和CronTrigger这两个子类。当仅需触发一次或者以固定时间间隔周期执行,SimpleTrigger是最适合的选择;而CronTrigger则可以通过Cron表达式定义出各种复杂时间规则的调度方案:如每早晨9:00执行,周一、周三、周五下午5:00执行等
- Calendar:org.quartz.Calendar和java.util.Calendar不同,它是一些日历特定时间点的集合。一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点
- Scheduler:Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中拥有各自的组及名称,组及名称是Scheduler查找定位容器中某一对象的依据。Scheduler可以将Trigger绑定到某一JobDetail中,这样当Trigger触发时,对应的Job就被执行。一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。可以通过SchedulerFactory创建一个Scheduler实例。Scheduler拥有一个SchedulerContext,它类似于ServletContext,保存着Scheduler上下文信息,Job和Trigger都可以访问SchedulerContext内的信息。
- ThreadPool:Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。
更详细的内容可以参考http://www.blogjava.net/baoyaer/articles/155645.html
在这列出再多例子都没有附件中的例子好,所以就不费口舌了。
- quartz_examples.rar (49 KB)
- 下载次数: 166
发表评论
-
关于继承的例子
2011-11-19 15:13 1236继承是再普通不过的概念,但是你真的能玩的转吗? 父类Perso ... -
Object类分析equals、hashcode、clone
2011-11-17 21:57 1858Object类中的equals: publ ... -
成员变量的初始化
2011-11-16 16:15 1084Java会对成员变量进行自动初始化,并且在构造方法执行之前完成 ... -
关于java多线程的一篇不错的入门级文章
2011-11-14 22:42 1950虽然都是老生常谈,而且入门级,但是讲的很不错。 一、理解多线 ... -
多线程常用方法比较汇总
2011-11-15 23:07 1603从操作系统的角度讲,o ... -
多线程例子:yield
2011-11-14 20:59 1605public class Test { public ... -
String的valueOf方法传入null
2011-11-12 20:42 13815这个问题很有意思 Object obj = null; ... -
多线程例子:join
2011-11-09 23:06 1376package sure; import java. ... -
多线程例子:wait与notify、sleep
2011-11-09 22:15 3343package sure; import org.s ... -
JAVA编程经验汇总
2011-11-04 21:04 1245都是一些小的点,不完 ... -
以ConcurrentHashMap为例小议并发集合类
2011-08-09 22:15 5107为了引出并发集合类ConcurrentHashMap,有必要先 ... -
聊一下Java代理那点事
2011-08-06 20:08 2017代理模式 代理模式的作用是:为其他对象提供一种代理以控制对 ... -
说说volatile关键字
2011-08-05 16:29 2357Java语言规范中指出:为 ... -
关于Java包装类装箱拆箱的小例子
2011-07-27 09:50 1477简单来说:装箱就是把值类型转变为引用类型,拆箱就是把引用类型转 ... -
深入浅出Java回调机制
2011-07-21 21:24 83345前几天看了一下Spring的部分源码,发现回调机制被大量使用, ... -
Java多线程总结之聊一聊Queue
2011-07-17 23:13 36876上个星期总结了一下synchronized相关的知识,这次将Q ... -
Java多线程总结之由synchronized说开去
2011-07-10 17:19 22487更新完毕,结贴,以后有新的想法再开新帖 这几天不断添加新内容, ... -
关于递归
2011-06-18 21:27 109算法中有调用自身,则是递归 递归算法必须是逐步有规律简化的, ... -
java的内部类与匿名类
2011-06-18 13:19 1815提起Java内部类(Inner Class)可能很多人不太熟悉 ... -
Java线程同步机制synchronized关键字的理解
2011-06-18 08:49 37由于同一进程的多个线 ...
相关推荐
【疾病分类】 GUI SVM大脑疾病(脑瘤)和神经疾病(动脉瘤)分类【含Matlab源码 4093期】
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
HC200-10标定版描述文件及标定版ps文件
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
顾客模具验收鉴定报告.doc
2020年度SaaS企业 TOP100.docx
9培训申请单.xls
23数据技术 森林火灾预测系统 高品琦 商业计划书.docx
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
风险与机会评价与应对策划表.xls
31客户满意度汇总表.xls
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
与大学团队合作,设计一个包含 Raspberry Pi、摄像头模块和基于 YOLOv5 的对象检测算法的系统。• 开发了能够识别和分类各种交通标志的实时交通标志检测和分类系统
python读取excel数据 python读取excel到数据库中,简单的数据库管理脚本
成本中心领(退)料单.XLS
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作