java多线程学习之6Timer类的作用(定时器类的作用)

java.util.Timer你就把它想像成是一种特殊类型的Thread类的子类。
即java.util.Timer extends Thread(在逻辑意义上,而并非在物理实现上)正解为:与每个 Timer类型 对象相对应的是单个后台线程thread,这个单个后台thread用于顺序地执行所有计时器任务(TimerTask类型的Runnable类型对象)(即嫁接到该Timer类型对象的所有TimerTask实例任务)。

计时器任务(TimerTask类型实例的run()方法的方法体内代码指令们)应该迅速被这个thread所执行完成。如果完成某个计时器任务(TimerTask类型实例的run()方法)的执行时间太长,那么它会“独占”计时器(该Timer实例)的任务执行线程(每一个Timer实例都会一一对应一个独立的thread这是java自己内部实现的你无须操心,只要知道这个事情的原理就行)。因此,这就可能延迟后续任务(其它的TimerTask类型实例的run()方法体)的执行,而这些等待的任务(TimerTask类型实例)就可能“堆在一起”,并且在上述不友好的任务(前文提到的不友好耗时的先行TimerTask类型实例)最终完成时才能够被快速连续地执行(这里指的被快速连续执行的是后续那些被堆在一起的没有按照原时间计划被及时执行的任务)。 注意:被java.util.Timer所执行的任务(Runnable类型对象)必须是TimerTask这种类型的任务。
____________________________________________________________________________________________________
一个java.util.Timer的实例化对象可以被想象成一个有着特殊功能的thread(线程)对象.但是实际上java.util.Timer并不是Thread类的子类型.真实的存在情况是:java会为每一个Timer类型实例化对象对应创建一个Thread类型的实例化对象,并让二者保持着一一对应的关系.该后台存在的thread会为其对应的timer实例服务.且是一一对应关系.这个thread就是该timer专门用来运行TimerTask类型实例(任务)来用的!(权威)

java.util.Timer类较Thread类的特别之处在于,Timer具有时间限定与时间设定的特性,即Timer具有计划(时间计划)执行任务(Runnable类型实例化对象才是任务)的特性。换句话说:Timer类型的实例化对象是具有时间计划执行特性的thread(线程)对象(真实原理是每一个Timer类型实例都对应与一个Thread类型实例进行了一一对应的绑定,这个Thread类型对象就是为该Timer类型对象服务的,并且Timer类型对象将与它一一绑定的那个thread专用于去执行TimerTask类型任务)。因此每一个Timer类型实例就是一个thread实例(线程实例).即一个Timer timer 在意义上(撇开时间特性来说)就是一个 Thread thread,即你可以理解为:一个timer就是一个thread.就是一个合理的假想而已,真实的情况并不是这样的!(权威)

____________________________________________________________________________________________________________________________________
Timer就是具有时间计划(可按照计划设定时限去执行相关任务)特性的一种Thread(线程类型)这仅仅是一个合理的假想而已,真实的情况并不是这样的!(权威)

Timer就是具有时间计划特性(时间限定与时间设定特性)的Thread,这仅仅是一个合理的假想而已,真实的情况并不是这样的!(权威)

(真实原理是每一个Timer类型实例都对应与一个Thread类型实例进行了一一对应的绑定,这个Thread类型对象就是为该Timer类型对象服务的,它专用于去执行TimerTask类型任务)。
_______________________________________________________________________________________________________________________________________________________

详细剖析java.util.Timer的内部构造:
每一个java.util.Timer对象是由如下部分组成的,一个与该Timer类型对象一一对应绑定的Thread类型对象 Thread thread,一个Queue<TimerTask> timerTasksQueue,注意:该Queue<TimerTask> timerTasksQueue是个"任务队列",期内被存放的TimerTask类型实例任务,会被"排队"(按照FIFO原则先入先出first in,first out的原则去排队等待该thread处理它们),即该thread对象就是该Timer类型对象专门用来顺序接收与处理该timerTasksQueue中的各个排了队的TimerTask类型实例任务的.
__________________________________________________________________________________________________________________________________________
注意:一个java.util.Timer类型对象aTimer 仅仅与一个Thread类型对象 aThread一一对应,当一个aTimer上面启动了多个TimerTask类型实例化对象时,aTimer会把这些多余的TimerTask类型对象(任务实例,特殊的Runnable类型实例)放入该aTimer对象对应的那个Queue<TimerTask> timerTasksQueue队列中,让这些多余TimerTask对象在其内排队等待执行(等待被该aThread所接受并嫁接寄生到其上已获得被执行的能力),这就是所谓的“当单个定时器aTimer上绑定了多个TimerTask类型任务时,单一的处理thread(aTimer对应的那个thread即aThread)在没有及时处理多个TimerTask类型任务的情况下,会导致这些TimerTask实例会被放在任务队列Queue<TimerTask> timerTasksQueue中堆积下来,排队等待该aThread的闲置档期”,这就是所谓的"单个Timer实例绑定多个任务时,导致任务的堆积现象".

要想处理该现象:"单个Timer实例绑定多个任务时,导致任务的堆积现象".方法如下:
针对每一个TimerTask实例化任务一一对应为其创建单一的java.util.Timer类型对象,这样用一个Timer实例去仅仅处理一个TimerTask实例意味着仅仅一个TimerTask实例绑定到该Timer实例所对应的那个单一的thread上,这样就不会出现任务堆积现象,因为任务(TimerTask类型实例)仅有一个,让一个thread仅仅去处理一个timerTask那是小KISS,没问题这样不会存在任务堆积现象,因为任务堆积现象的前提是,让一个thread去处理多个任务(让一个thread去同时处理多个任务它才会有可能出现处理不过来的情况,才会出现任务堆积现象),因此避免该现象的一个好的方式就是让Timer实例与一个TimerTask实例一一对应,即每有一个TimerTask类型实例就新为其创建一个Timer类型实例,让该Timer类型实例与该TimerTask实例做到一一对应,不带别人玩儿.这样我们就无需担心task的堆积.

____________________________

篇外话题:另一种Timer

众所周知:Swing组件对象不能根据从任意地thread(线程)中去调用,这也包括java.util.Timer类型对象,因为Timer本身就是具有线程特性的(更确切地说是Thread特性,即你可以把java.util.Timer想成是一种特殊类型的Thread)(Timer本身就是个Thread即一个java.util.Timer类型的实例化对象就相当于一个thread)虽然我们可以利用SwingUtilities这个工具类的invokeLater()方法与invokeAndWait()方法来实现"间接"在其他线程中调用Swing组件的效果.其实仍然是(间接)扩展到事件派发线程中去调用Swing组件对象的。注意:java也提供了只为Swing组件对象使用的Timer类型类它就是:javax.swing.Timer这个类.这个类提供了在特定时间执行动作(动作事件)的能力,且这个动作(事件)是从事件派发线程中被执行(触发)(激活)(调用)的.(权威)
_______________________________________________________________________________________________
javax.swing.Timer这个类的实例它能够确保绑定到其上"任务"是在事件派发线程这个thread上去运行的!因为此时的"任务"代码指令部分是写在监听器处理程序{}内的(即任务指令是被写在事件处理函数的函数体内的).(注意:事件处理函数的函数体内代码默认情况下都是在swing的事件派发线程上被执行的),swing技术中有个叫"事件对象排队用的队列"这么个概念,从swing技术产生的UI界面上,当有用户所激发(触发)出来的Event(事件)类型对象时,多个并发的事件对象会被排队到前文提到的"事件队列"Queue<Event> eventsQueue中去,这些事件对象会按照FIFO原则排队并以此原则出队列后顺序地被Swing的事件派发线程所处理。由于“这些事件的触发,即各个事件对象的激活彼此间不可能并发产生,人点不了那么快,且彼此之间的间隔延时针对于计算机而言是很长时间的,计算机完全有足够的时间与精力去顺序地串行化处理响应这些事件(按照各个事件对象进入事件队列的顺序FIFO的排队顺序处理各个事件,对依次出队列的事件做出响应回调),对人的感官来说这个时间却很短,因此即使利用事件派发线程这个单一的后台线程去处理对这些排队了的事件对象的响应回调处理的启动,人也是感觉不到慢的,即人是感觉不到各个事件对象的排队等待,与顺序性地被事件派发线程串行化处理的,因为太快了你无法感知”(权威),至此虽说SWING技术对于各个事件的处理是单线程的串行化(按照事件在事件队列中排队的先后顺序)处理,但是你仍不会感觉到响应慢,因为计算机的运算速度是很快的,而你的顺序化操作的速度(顺序化的产生事件对象的速度)对于计算机而言永远都是很满的,因此计算机完全有能力处理你的"快速操作,即使你是飞龙探云手,或降龙十八掌"
_____________________________________________________________________________________________
切记一句话:SWING程序对事件的响应处理永远都是单线程的,即SWING技术仅仅利用一个单一的其内置的"事件派发线程"(事件处理线程)而已去串行化回调对于各个事件对象的响应处理。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值