- 浏览: 310845 次
- 性别:
- 来自: 武汉
最新评论
-
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 1273继承是再普通不过的概念,但是你真的能玩的转吗? 父类Perso ... -
Object类分析equals、hashcode、clone
2011-11-17 21:57 1897Object类中的equals: publ ... -
成员变量的初始化
2011-11-16 16:15 1118Java会对成员变量进行自动初始化,并且在构造方法执行之前完成 ... -
关于java多线程的一篇不错的入门级文章
2011-11-14 22:42 2020虽然都是老生常谈,而且入门级,但是讲的很不错。 一、理解多线 ... -
多线程常用方法比较汇总
2011-11-15 23:07 1636从操作系统的角度讲,o ... -
多线程例子:yield
2011-11-14 20:59 1644public class Test { public ... -
String的valueOf方法传入null
2011-11-12 20:42 13931这个问题很有意思 Object obj = null; ... -
多线程例子:join
2011-11-09 23:06 1406package sure; import java. ... -
多线程例子:wait与notify、sleep
2011-11-09 22:15 3379package sure; import org.s ... -
JAVA编程经验汇总
2011-11-04 21:04 1287都是一些小的点,不完 ... -
以ConcurrentHashMap为例小议并发集合类
2011-08-09 22:15 5158为了引出并发集合类ConcurrentHashMap,有必要先 ... -
聊一下Java代理那点事
2011-08-06 20:08 2088代理模式 代理模式的作用是:为其他对象提供一种代理以控制对 ... -
说说volatile关键字
2011-08-05 16:29 2391Java语言规范中指出:为 ... -
关于Java包装类装箱拆箱的小例子
2011-07-27 09:50 1545简单来说:装箱就是把值类型转变为引用类型,拆箱就是把引用类型转 ... -
深入浅出Java回调机制
2011-07-21 21:24 83475前几天看了一下Spring的部分源码,发现回调机制被大量使用, ... -
Java多线程总结之聊一聊Queue
2011-07-17 23:13 36975上个星期总结了一下synchronized相关的知识,这次将Q ... -
Java多线程总结之由synchronized说开去
2011-07-10 17:19 22637更新完毕,结贴,以后有新的想法再开新帖 这几天不断添加新内容, ... -
关于递归
2011-06-18 21:27 109算法中有调用自身,则是递归 递归算法必须是逐步有规律简化的, ... -
java的内部类与匿名类
2011-06-18 13:19 1887提起Java内部类(Inner Class)可能很多人不太熟悉 ... -
Java线程同步机制synchronized关键字的理解
2011-06-18 08:49 37由于同一进程的多个线 ...
相关推荐
本文主要探讨了小议外汇期权会计在新规则中的应用,涉及到外汇期权的概念、分类、确认、计量和披露等方面的知识点。 一、外汇期权的概念 外汇期权是一种金融衍生工具,允许持有人在未来某个时间点选择是否执行外汇...
小议图书馆网站的创立和维护.doc
小议企业管理体制的特点和经验.doc
小议经济型酒店消费者心理及消费方向.doc
也就是说,可以把图像 I1 独立编码,另一幅图像 P1 通过已编码的 I1 进行预测,这种思想和时序预测编码非常相似。 由于左右两个视频序列 3D 场景和相机参数(焦距)的一致性,对视频编码对的两个图像(如 I1,P1)的...
### 抖动算法小议——深入探讨多媒体技术中图像的抖动算法 #### 引言 在多媒体领域,尤其是在图像处理技术中,抖动算法扮演着至关重要的角色。本文旨在通过对抖动算法的深入解析,帮助读者理解其原理及其在灰度...
**小议MVC模式开发** MVC(Model-View-Controller)模式是一种广泛应用于Web应用程序设计的架构模式,它的核心思想是将业务逻辑、数据处理和用户界面进行分离,以提高代码的可维护性和可扩展性。在本文中,我们将...
小议日本循环型社会的形成和改进中学习.doc
小议计算机电子信息工程技术的应用和安全管理.pdf
【小议一年级教学解决问题的现状和解决策略】 数学是一门高度抽象和概括的学科,对于刚入学的一年级学生来说,可能会感到相对枯燥无趣。在这个关键的学习阶段,培养学生的解决问题能力至关重要,因为这不仅影响他们...
【文章摘要】本文主要探讨了在新的形势下大额现金管理的重要性,特别是...总之,面对大额现金管理的新挑战,需要政策制定者、金融机构和社会各方面共同努力,构建更为严密的反洗钱防线,保障经济金融秩序的稳定和安全。
小议嵌入式计算机技术.pdf
法治思想起源小议.docx
小议食品安全问题.doc
为了确保整体时序的完整性,需要专门的工具来检查高层模块间的时序和整体网络线路的一致性。此外,任何局部变化都可能影响整体时序,因此,需要工具来检测和解决新出现的时序问题。 在设计过程中,还需要考虑物理...
小议人力资源外包.doc
小议“地摊经济”合集