【原】定时器与系统时间(续)

额外问题处理:

--------------------------------------------------------------------------------

13) 定时器之外的一些处理
    a) window环境下,定时器通知执行定时任务的时间点可能误差1毫秒;Linux环境也有类似情况,但是误差频率低很多(只是在指定时间点前后1毫秒误差,心跳步长不差)
        可能的影响:
            以每秒任务为例, 10:00:00.000 TaskA -> 10:00:00.999 TaskB -> 10:00:02.000 TaskC -> 10:00:03.001 TaskD
            会导致第2个任务(TaskB)丢失, 因为步长是1秒钟 + 抹去毫秒计算
        代码解决方案:
            定时器初始时间设置为 XX:XX:XX:500,以两秒的中间段为起点开始心跳,这样误差1毫秒时候,抹去毫秒不影响正常定时器执行

    Calendar cal = Calendar.getInstance();
    int millis = cal.get(Calendar.MILLISECOND);
    int delay = (1500 - millis) % 1000;        // 下个0.5秒开始运行(定时器偶尔会前后误差1毫秒)
    timerService.scheduleAtFixedRate(new Runnable() {..}, delay, TIMER_STEP, TimeUnit.MILLISECONDS);

b) 线程池启动,大概会延迟200毫秒后才开始心跳

没有多大不良影响
    c) 心跳时间点未 XX:XX:XX:500, 正常情况下没有问题。
        问题是每小时同步一次服务器系统时间,可能依然导致心跳时间点押到 XX:XX:XX:000 上,从而引起问题a),当然这个概率极低
        可以考虑心跳时长为 100毫秒
    d) 任务执行接口传入当前时间作为参数
        定时器(心跳)线程,定时挑选符合执行条件的任务,扔到任务池去执行。
        因为任务执行时间过长、任务锁、线程池资源不足等条件导致的任务内部log时间不符合要求是任务本身的事情,反正定时器通知你了,不用纠结定时器问题
    e) 任务有唯一id,防止重复添加任务, 一次性任务没有Id
        任务基类对id做了处理,加了统一前缀,方便log跟踪

定时任务优化:

--------------------------------------------------------------------------------

14) 现在定时器定时执行任务的功能已经完成:我在指定的时间通知你做指定的任务。不过总有一些奇怪的任务,用这样更简单的语言不方便表达。
    比如,每隔10分钟统计一次在线人数。
    当前接口可以处理,不过感觉非常笨拙:

        regPerHourTask (0, 0, TaskA);
        regPerHourTask (10, 0, TaskA);
        regPerHourTask (20, 0, TaskA);
        regPerHourTask (30, 0, TaskA);
        regPerHourTask (40, 0, TaskA);
        regPerHourTask (50, 0, TaskA);

当然也可以尝试

        regPerMinuteTask (0, new Task () {
            每10次执行1次,忽略9次
        });

于是抽象出一个固定分钟执行的任务,你告诉我你要几分钟执行一次,然后实现我的执行接口就是了

这样又产生了一个新的问题,比如,每隔5分钟统计一次在线人数。

        2014-12-20 13:58:12,503 INFO 人数为N // 当前log是
        2014-12-20 13:03:12,503 INFO 人数为N
        2014-12-20 13:08:12,503 INFO 人数为N
        2014-12-20 13:13:12,503 INFO 人数为N
        2014-12-20 13:18:12,503 INFO 人数为N
        2014-12-20 13:22:53,321 INFO 人数为N // 重启服务器后:
        2014-12-20 13:27:53,321 INFO 人数为N
        2014-12-20 13:32:53,321 INFO 人数为N
        2014-12-20 13:37:53,321 INFO 人数为N

看起来有点小晕

解决方案:
        固定分钟执行的任务, 初始增加一个 baseTime 参数, 时间计算依赖 baseTime 去选择执行或忽略

        2014-12-20 13:00:00,000 INFO 人数为N  // 当前log是
        2014-12-20 13:05:00,000 INFO 人数为N
        2014-12-20 13:10:00,000 INFO 人数为N
        2014-12-20 13:15:00,000 INFO 人数为N
        2014-12-20 13:20:00,000 INFO 人数为N
        2014-12-20 13:30:00,000 INFO 人数为N  // 重启服务器后
        2014-12-20 13:35:00,000 INFO 人数为N
        2014-12-20 13:40:00,000 INFO 人数为N
        2014-12-20 13:45:00,000 INFO 人数为N

这样 grep 出来log对时间就舒服多了

定时任务优化(二):

--------------------------------------------------------------------------------

15) 先做了到点通知功能,后来额外加了定时通知功能;突然发现,这个只是个正常的任务功能,还有不正常的情况。
    比如,我们需要远程请求加载数据,可能这数据相对重要一些,但是只要一次取对的数据就可以了,问题它可能失败。
    换个描述方式就是,我需要去其它地方拿数据,直到拿到为止。当然现在的定时器也支持这个任务,尽管不友好:
        注册一个每分钟任务,如果发现任务完成了,就移除。
    但是实际问题可能更复杂一些:
        如果任务执行失败,我就5秒后再执行一次;
        如果再失败,我就30秒后执行一次;
        如果再失败,就3分钟后执行;
        如果再失败,就算了,不能无休止执行;也可能过了一定期限后,执行成功也没有意义
    在自己的任务里可以自行处理类似逻辑,不过这也是可以抽象的,于是需要增加一个固执的任务,失败后休息一定时间再执行
    规定的失败次数(可尝试次数)用完后,没有完成也不再执行了
    这里的需要通知任务执行的时候,执行函数是有成功与否的返回值。

总结

--------------------------------------------------------------------------------

16) 总结
    a) 定时器通知【可以执行的指定任务】了
    b) 定时器【定时】通知【可以执行的指定任务】了
    c) 定时器【多次】通知【需要执行成功的指定任务】了
    d) 定时器顺便解决了服务器系统时间问题

时间: 2024-08-11 08:42:32

【原】定时器与系统时间(续)的相关文章

【原】定时器与系统时间

问题:--------------------------------------------------------------------------------用户反馈一些定时活动提前开启或者延后开启1) 登录服务器,查看时间确实慢了或者快了.总之是有几台服务器时间不准确了.2) 查看代码是使用的ScheduledExecutorService.scheduleAtFixedRate,Java的API,不至于这里存在Bug3) 查看log4j日志输出发现:    12点的定时活动,之前的[

标准IO的简单应用,动静态库,读取系统时间并打印,模拟ls -l功能

2015.2.27星期五,小雨 标准IO实现的复制功能: #include <stdio.h>#include <errno.h> #define N 64 int main(int argc, char *argv[]){ int n; char buf[N]; FILE *fps, *fpd; if(argc < 3) { printf("usage : %s <src_file><dst_file>\n",argv[0]);

C语言获取系统时间的几种方式

C语言获取系统时间的几种方式 2009-07-22 11:18:50|  分类: 编程学习 |字号 订阅 C语言中如何获取时间?精度如何? 1 使用time_t time( time_t * timer ) 精确到秒2 使用clock_t clock() 得到的是CPU时间 精确到1/CLOCKS_PER_SEC秒3 计算时间差使用double difftime( time_t timer1, time_t timer0 )4 使用DWORD GetTickCount() 精确到毫秒5 如果使用

[2014.5.22][UBUNTU]Ubuntu与Windows系统时间不同步的问题

安装Ubuntu+Windows双系统时会遇到Windows和Ubuntu系统时间不同步的问题,这是因为Windows系统默认读取主板bios等硬件系统时间作为OS的当地时间;而MAc,Linux类的OS以主板bios等硬件系统时间作为UTC时间,然后操作系统的时间以UTC为标准按照使用者的时区设置加加减减.这就造成了中国用户会出现一个很有趣的现象:Ubuntu上的时间会比windows上的快8小时(至于是怎么算的 请童鞋自己掰手指头;是不是寓意Ubuntu快windows一筹?). 解决这个问

wpf 窗体中显示当前系统时间

先看一下效果: 这其实是我放置了两个TextBlock,上面显示当前的日期,下面显示时间. 接下来展示一下代码: 在XAML中: <StackPanel Width="205"                    Margin="0,0,57,0"                    HorizontalAlignment="Right">            <TextBlock Height="Auto&qu

关于时间的操作(JavaScript版)——年月日三级联动(默认显示系统时间)

这个功能是大学时自己使用纯JavaScript写的,没有借助Jquery,呵呵呵,看起来有点繁琐,可是在当时依稀的记得功能实现后自己好好的高兴一把了呢,从现在来看那时候的自己是多么的幼稚.多么的无知: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>年月日三级联动(默认显示系统时间)</title> <

MFC在static text中动态显示系统时间

1.添加static text ,ID为IDC_ShowTime 2,在OnInitDialog()中 SetTimer(1,1000,NULL);         //启动定时器 3.添加WM_TIMER消息处理函数,ontimer中添加如下代码: CString strTime; CTime tm; tm=CTime::GetCurrentTime(); strTime=tm.Format("%Y-%m-%d %H:%M:%S"); SetDlgItemText(IDC_ShowT

[转载]如何使Android应用程序获取系统权限来修改系统时间

在 android 的API中有提供 SystemClock.setCurrentTimeMillis()函数来修改系统时间,可惜无论你怎么调用这个函数都是没用的,无论模拟器还是真机,在logcat中总会得到"Unable to open alarm driver: Permission denied ".这个函数需要root权限或者运行与系统进程中才可以用. 本来以为就没有办法在应用程序这一层改系统时间了,后来在网上搜了好久,知道这个目的还是可以达到的. 第一个方法简单点,不过需要在

解决weblogic与系统时间相差8小时的问题

解决weblogic与系统时间相差8小时的问题 在一般情况下weblogic与系统时间是很少会出现时间差的问题,但有可能在某一特定的情况下就会出现,如使用weblogic8版本时可能会出现时差问题: 调整时差方法: 第一步: 1.找到D:\bea\jdk142_08\jre\lib\zi\Etc和D:\bea\jrockit81sp5_142_08\jre\lib\zi\Etc找到这两个文件夹里的Etc这个文件夹,里面就是时区文件, 第二步: 2.将GMT-8这个文件复制一份然后重命名为GMT来