JAVA/Android 笔记 定时/循环任务以及动画(Animator)
来源:互联网 发布:上海火速网络 编辑:程序博客网 时间:2024/06/06 14:24
定时任务/循环任务
在研究程序的时候,我经常会考虑一个问题,就是 :
如何有效率的执行一个定时任务。
初学的时候,书上提到过一些这样的情况,然后会告诉我使用一些什么API来执行这样的任务。
1. 使用Thread.sleep(long time)
。这个很好理解,就是新开一个线程,然后让这个线程sleep一段时间,再执行,这就是最好理解的定时执行。
2. 使用Timer.schedule()
,然后置入一个Timertask
。Timer是JAVA里面专门用来执行定时任务的API,Timertask实现了runnable接口,定时器会在设定的时间段内执行。
3. 使用ScheduledExecutorService
具体使用方法例如:
ScheduledExecutorService service = Executors .newSingleThreadScheduledExecutor();service.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.SECONDS);
与之前的两个方法相比,这个方法是使用的线程池,而timer是创建一个单线程来执行。所以这个效率更好。
(我没有使用过这个方法,这个我也是才知道的。)
参考:java实现定时任务的三种方法
原理探索
一般情况使用这3种方法就可以了。事实上还有一些java第三方库,可以提供一些有效的其他方法来实现这些任务。但是:
只会用“库”算不得什么本事。
我需要了解一些原理。这个到底是怎么执行的,官方API是如何运行的。
以及如何自己编写一个类似的程序/库
实际上如果探究底层代码的话,从android的代码里面可以看到很多native
字样,也就是说,这些是在底层用C语言写的,看不到。那就不管这些,最起码研究下可以看到的内容。
Timer类
首先,我发现Android里面的Timer和JAVA SE里面的有些不同。(当然也找到了一些其他地方的不同。)
但是我认为应该区别不大。
Android studio里面可以很方便的查看官方API 函数的代码,所以我查看的是Android里面的代码。
- 在Timer创建的时候,会创建一个线程
TimerThread
。线程立即开始运行。这个线程是扩展的Thread的自建类,里面有一个方法叫mainloop
,里面是一个while(true)
的循环,退出条件在内部设置。在TimerThread
启动的时候,就会开始运行mainloop
。 - 里面还有一个
TaskQueue
,保存的是一个TimerTask的数组,在mainloop里面会挨个运行这个数组里面的任务。在循环里面会对queue加锁(synchronized)。 - 因为是定时任务,所以在
TimerTask
里面会保存这个任务的运行时间,以及循环间隔时间(如果有的话)。在上面将的mainloop里面,每次循环会查找当前taskQueue里面的任务,对比timertask的运行时间是否是当前时间。如果是,就运行,如果不是就等待下一次循环。 mainloop
的退出条件是queue.isEmpty()
。每次循环的时候都会检查。如果定时任务是单次的,那么运行以后就会被移除taskqueue,如果是循环的,就会在执行以后移动到queue的末尾。- 因为这个是使用工作线程,所以为了避免造成资源浪费,设置了一个等待条件。如果
queue.isEmpty()
并且newTasksMayBeScheduled=true
,就执行queue.wait()
。这个方法告诉程序把当前queue对象锁挂起,不再占用cpu资源。直到有新任务进入,会调用queue.notify()
,告诉queue对象的锁可以开始运行了。
基本上Timer
的原理就是这些,代码比较短,所以容易读懂。
参考:Java线程间的通信方式详解
Animator
Android有一个很好用的动画组件叫ValueAnimator
,可以设置起始值/目标值,duration等参数,就可以很平滑的在设置的起始值到目标值之间变化。为了实现动作,也需要设置一个listener。
我想研究下这个类到底是用什么方法实现定时任务的。说实在的,其他的东西都好解决,无非就是考虑周到一点,写的全面一点,各种情况都照顾到,功能就能实现,我是想探索一下到底用什么办法能最有效的实现定时功能。(探索的是底层实现,而不是普通实现,如果要简单的实现定时功能,Android和JAVA给我们提供了好几种方法,timer,handler,等等)
我打开ValueAnimator的源码一看,果然很复杂,我一时间甚至都找不到怎么循环的。总不能就进行了一帧就结束了吧。
在这之前我还查看了Handler
,这个类用postDelay
实现了定时功能。我往伸出了找,果然发现了native方法,果然还是用native来实现了。看来探索到此为止了。(C语言几乎忘光了,正准备从头开始复习一下)
那么ValueAnimator
是怎么实现定时呢?我在层层深入加网上查询的帮助下发现,原来是借助handler实现了,也就是说,先计算出中间的关键帧的时间/值,然后往handler
里面sendMessageAtTime
,顾名思义,也就是在关键帧的时间点发送信息,handler接收到以后就处理,也就是运行到关键帧的值位置。
看来直接使用handler是比较有效率的做法。
参考:Animator
参考:Handler
- JAVA/Android 笔记 定时/循环任务以及动画(Animator)
- Android Animator(Android动画)
- Android Animator(Android动画)
- Android——Animator笔记:属性动画
- android定时循环执行任务
- android定时循环执行任务
- Android执行定时循环任务
- Android 定时循环任务实现
- android属性动画Animator(一)
- Android动画机制学习---animator(二)
- android animator 动画
- android animator 动画
- android动画 -- Property Animator
- android属性动画animator
- Android动画之Animator
- Android属性动画(Animator)
- Android动画之Animator
- android 简单动画Animator
- 关于空格代替程序后续
- 复制输入到输出将其中的制表符替换为\t
- Dynamical SP with Entity Framework
- 链表的增删改查
- 802.11协议精读16:信道模型(SISO)以及Break Point距离
- JAVA/Android 笔记 定时/循环任务以及动画(Animator)
- Leetcode 152. Maximum Product Subarray
- PHP--预定义超全局变量
- Struts2.5 ERROR StatusLogger No log4j2 configuration file found. Using default configurati
- PHP---防止注入攻击
- 【30.36%】【codeforces 740D】Alyona and a tree
- Struts2.5-add log4j-core to the classpath
- PHP--model1模式、分层模式、mvc模式:
- 早上好