为什么要将Calender、TimeUnit与ScheduledExecutorService一起记录呢,因为ScheduledExecutorService实现定时任务需要用到Calender、TimeUnit类的时间相关的知识。

Calender

一、 如何创建 Calendar 对象
Calendar 是一个抽象类, 无法通过直接实例化得到对象. 因此, Calendar 提供了一个方法 getInstance,来获得一个Calendar对象, 得到的 Calendar 由当前时间初始化.

1 Calendar cal = Calendar.getInstance();

二、 字段详解
Calendar 中 set 和 get 时间都是通过在参数中填入不同的字段来实现的, 不过有部分字段的常量值与约定俗成的值不相同
下面字段我们以 1998 年 2 月 28 日 23 时 11 分 11 秒 来讲解

1 Calendar cal = Calendar.getInstance();
2 cal.set(Calendar.YEAR, 1998);
3 cal.set(Calendar.MONTH, 1);
4 cal.set(Calendar.DATE, 28);
5 cal.set(Calendar.HOUR_OF_DAY, 23);
6 cal.set(Calendar.MINUTE, 11);
7 cal.set(Calendar.SECOND, 11);

YEAR
默认情况下指示为年份.
例子中 YEAR 为 1998

MONTH
指示当前年中的月份数,一年中的一月的值为 0
需要注意的是 JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER 分别与 [0, 11] 对应, 在设置和获取日期时要格外注意

WEEK_OF_YEAR
指示当前年中的星期数. 一年中的第一个星期的值为 1.
例子中 WEEK_OF_YEAR 为 9

WEEK_OF_MONTH
指示当前月中的星期数. 一个月中第一个星期的值为 1.
例子中 WEEK_OF_MONTH 为 5

DAY_OF_MONTH
指示一个月中的某天. 它与 DATE 是同义词. 一个月中第一天的值为 1.
例子中 DAY_OF_MONTH 为 28

DATE
同 DAY_OF_MONTH

DAY_OF_YEAR
指示当前年中的天数. 一年中第一天的值为 1.
例子中 DAY_OF_YEAR 为 59

DAY_OF_WEEK
指示一个星期中的某天, 一周中第一天的值为 1.
需要 注意 的是, 与中国人的习惯不同, 此处一周中的第一天为 周日. 一周的顺序依次为: 周日(1), 周一(2), 周二(3), 周三(4), 周四(5), 周五(6), 周六(7) 在设置和获取日期时要格外注意

AM_PM
指示 HOUR 是在中午之前还是在中午之后. [0, 12) 为上午, AM_PM 值为 1 [12, 24)为下午, AM_PM 值为 0

HOUR
指示上午或下午的小时.
例子中 HOUR 为 11

HOUR_OF_DAY
指示一天中的小时。 HOUR_OF_DAY 用于 24 小时制时钟
例子中 HOUR_OF_DAY 为 23

MINUTE
指示一小时中的分钟
例子中 MINUTE 为 11

SECOND
指示一分钟中的秒
例子中 SECOND 为 11

三、 设置值

1 cal.set (2013, 5, 4, 13, 44, 51);//年月日时分秒 (月份0代表1月)
2 cal.set (Calendar.YEAR, 2014);//年
3 cal.set (Calendar.MONTH, 7);//月 (月份0代表1月)
4 cal.set (Calendar.DATE, 11);//日
5 cal.set (Calendar.HOUR_OF_DAY, 15);//时
6 cal.set (Calendar.MINUTE, 33);//分
7 cal.set (Calendar.SECOND, 32);//秒

四、 获取值

1 cal.get (Calendar.YEAR);//年
2 cal.get (Calendar.MONTH) + 1;//月 (必须要+1)
3 cal.get (Calendar.DATE);//日
4 cal.get (Calendar.HOUR_OF_DAY);//时
5 cal.get (Calendar.MINUTE);//分
6 cal.get (Calendar.SECOND);//秒
7 cal.get (Calendar.DAY_OF_WEEK);//星期 (Locale.ENGLISH情况下,周日是1,剩下自己推算)

五、 运算值

Add

cal.add (Calendar.YEAR, 1);//年
cal.add (Calendar.MONTH, 1);//月
cal.add (Calendar.DATE, 1);//日
cal.add (Calendar.HOUR_OF_DAY, -1);//时
cal.add (Calendar.MINUTE, 1);//分
cal.add (Calendar.SECOND, 1);//秒
cal.add (Calendar.DATE, 7);//周

六、 Calendar 对象间的比较
比较两个 Calendar 对象表示的时间值, 如果参数表示的时间等于此 Calendar 表示的时间,则返回 0 值;如果此 Calendar 的时间在参数表示的时间之前,则返回小于 0 的值;如果此 Calendar 的时间在参数表示的时间之后,则返回大于 0 的值。

以上摘自:https://www.cnblogs.com/a1439775520/p/13076018.html

TimeUnit

TimeUnit是java.util.concurrent包下面的一个类,表示给定单元粒度的时间段

常用的颗粒度

TimeUnit.DAYS          //天
TimeUnit.HOURS         //小时
TimeUnit.MINUTES       //分钟
TimeUnit.SECONDS       //秒
TimeUnit.MILLISECONDS  //毫秒1.颗粒度转换
public long toMillis(long d)    //转化成毫秒
public long toSeconds(long d)  //转化成秒
public long toMinutes(long d)  //转化成分钟
public long toHours(long d)    //转化成小时
public long toDays(long d)     //转化天import java.util.concurrent.TimeUnit;
public class TimeUnitTest {public static void main(String[] args) {//convert 1 day to 24 hourSystem.out.println(TimeUnit.DAYS.toHours(1));//convert 1 hour to 60*60 second.System.out.println(TimeUnit.HOURS.toSeconds(1));//convert 3 days to 72 hours.System.out.println(TimeUnit.HOURS.convert(3, TimeUnit.DAYS));}}
2.延时,可替代Thread.sleep()。import java.util.concurrent.TimeUnit;
public class ThreadSleep {public static void main(String[] args) {Thread t = new Thread(new Runnable() {private int count = 0;@Overridepublic void run() {for (int i = 0; i < 10; i++) {try {// Thread.sleep(500); //sleep 单位是毫秒TimeUnit.SECONDS.sleep(1); // 单位可以自定义,more convinent} catch (InterruptedException e) {e.printStackTrace();}count++;System.out.println(count);}}});t.start();}
}

以上摘自:https://www.jianshu.com/p/4ab62e4a328f

ScheduledExecutorService实现定时任务

一:简单说明

ScheduleExecutorService接口中有四个重要的方法,其中scheduleAtFixedRate和scheduleWithFixedDelay在实现定时程序时比较方便。
下面是该接口的原型定义

java.util.concurrent.ScheduleExecutorService extends ExecutorService extends Executor

接口scheduleAtFixedRate原型定义及参数说明

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit);

command:执行线程
initialDelay:初始化延时
period:两次开始执行最小间隔时间
unit:计时单位
注意:scheduleAtFixedRate ,是以上一个任务开始的时间计时,period时间过去后,检测上一个任务是否执行完毕,如果上一个任务执行完毕,则当前任务立即执行,如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行。

接口scheduleWithFixedDelay原型定义及参数说明

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit);

command:执行线程
initialDelay:初始化延时
period:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)
unit:计时单位
注意:scheduleWithFixedDelay,是以上一个任务结束时开始计时,period时间过去后,立即执行。

二:功能示例

1.按指定频率周期执行某个任务。

初始化延迟0ms开始执行,每隔100ms重新执行一次任务。

/*** 以固定周期频率执行任务*/
public static void executeFixedRate() {ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);executor.scheduleAtFixedRate(new EchoServer(),0,100,TimeUnit.MILLISECONDS);
}

间隔指的是连续两次任务开始执行的间隔。

2.按指定频率间隔执行某个任务。

初始化时延时0ms开始执行,本次执行结束后延迟100ms开始下次执行。

/*** 以固定延迟时间进行执行* 本次任务执行完成后,需要延迟设定的延迟时间,才会执行新的任务*/
public static void executeFixedDelay() {ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);executor.scheduleWithFixedDelay(new EchoServer(),0,100,TimeUnit.MILLISECONDS);
}

3.周期定时执行某个任务。

有时候我们希望一个任务被安排在凌晨3点(访问较少时)周期性的执行一个比较耗费资源的任务,可以使用下面方法设定每天在固定时间执行一次任务。

/*** 每天3点执行一次(在24小时内程序一定会执行完毕的情况下)* 每天定时安排任务进行执行*/
public static void executeEightAtNightPerDay() {ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);long oneDay = 24 * 60 * 60 * 1000;long initDelay  = getTimeMillis("03:00:00") - System.currentTimeMillis();initDelay = initDelay > 0 ? initDelay : oneDay + initDelay;executor.scheduleAtFixedRate(new EchoServer(),initDelay,oneDay,TimeUnit.MILLISECONDS);
}/*** 获取指定时间对应的毫秒数* @param time "HH:mm:ss"* @return*/
private static long getTimeMillis(String time) {try {DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");DateFormat dayFormat = new SimpleDateFormat("yy-MM-dd");Date curDate = dateFormat.parse(dayFormat.format(new Date()) + " " + time);return curDate.getTime();} catch (ParseException e) {e.printStackTrace();}return 0;
}4.辅助代码
class EchoServer implements Runnable {@Overridepublic void run() {try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("This is a echo server. The current time is " +System.currentTimeMillis() + ".");}
}

三:一些问题

上面写的内容有不严谨的地方,比如对于scheduleAtFixedRate方法,当我们要执行的任务大于我们指定的执行间隔时会怎么样呢?

对于中文API中的注释,我们可能会被忽悠,认为无论怎么样,它都会按照我们指定的间隔进行执行,其实当执行任务的时间大于我们指定的间隔时间时,它并不会在指定间隔时开辟一个新的线程并发执行这个任务。而是等待该线程执行完毕。

源码注释如下:

* Creates and executes a periodic action that becomes enabled first
* after the given initial delay, and subsequently with the given
* period; that is executions will commence after
* <tt>initialDelay</tt> then <tt>initialDelay+period</tt>, then
* <tt>initialDelay + 2 * period</tt>, and so on.
* If any execution of the task
* encounters an exception, subsequent executions are suppressed.
* Otherwise, the task will only terminate via cancellation or
* termination of the executor.  If any execution of this task
* takes longer than its period, then subsequent executions
* may start late, but will not concurrently execute.

根据注释中的内容,我们需要注意的时,我们需要捕获最上层的异常,防止出现异常中止执行,导致周期性的任务不再执行。

以上摘自:https://blog.csdn.net/tsyj810883979/article/details/8481621/

学习记录466@Java Calender类、TimeUnit类以及 ScheduledExecutorService实现定时任务相关推荐

  1. Java快速入门学习笔记7 | Java语言中的类与对象

    有人相爱,有人夜里开车看海,有人却连LeetCode第一题都解不出来!虽然之前系统地学习过java课程,但是到现在一年多没有碰过Java的代码,遇到LeetCode不知是喜是悲,思来想去,然后清空自己 ...

  2. java基础案例教程前4章知识点_java学习记录4 Java基础知识点

    java学习记录4 Java基础知识点 1. 注释 单行注释 使用"//"开头,后面是注释的内容 一般在要注释的语句的上面加注释 多行注释 以"/*"开头,以& ...

  3. IDL学习记录和Java调用IDL方法

    IDL学习记录和Java调用IDL方法 2018年02月06日 08:32:02 回首1949 阅读数:385更多 个人分类: 随想 版权声明:乐呵乐呵得了 https://blog.csdn.net ...

  4. gradle exclude_Gradle学习记录020 java工程的测试 part1

    详细学习如何用Gradle测试java工程.第二部分.该学习记录基于Gradle官方网站资料.本篇参考链接如下: https://docs.gradle.org/current/userguide/j ...

  5. C++学习记录8:定义一个分数类Score和学生类Student

    (1)定义一个分数类Score.它有3个数据成员: Chinese       //语文课成绩 English       //英语课成绩 Mathematics   //数学课成绩 2个构造函数:无 ...

  6. Java学习记录:Java飞机大战进阶版(敌人有子弹、有生命、有boss、有声音、还有大招一键清屏)

    Java飞机大战 序言 一.项目需求分析 二.各个对象类的设计 加载图片类Images 抽象类FlyingObject 天空类Sky 小敌机类Airplane 大敌机类BigAirplane 侦察机类 ...

  7. Redis学习记录之Java中的初步使用

    [html] view plain copy  redis下载地址:<span style="font-family: Arial, Helvetica, sans-serif;&qu ...

  8. 懒癌患者的学习记录之JAVA冒泡排序代码

    冒泡排序 冒泡排序基本思路: 从第零位开始,依次与后一位进行比较并将较大的往后排较小的往前排.第一次循环就会将最大的值排在最后一位,第二次循环会将第二大的值排在倒数第二位,以此类推. JAVA冒泡排序 ...

  9. (JavaSE 学习记录)Java运算符

    算术运算符注意项 如果两个操作数有一个为Long, 则结果为Long. 没有long时,结果为int.即使操作数全为short,byte,结果也是int. 如果两个操作数有一个为double,则结果为 ...

最新文章

  1. 张晓帆:一个决定将47万奖金全部投入科研的博士生
  2. iOS自定义简易刷新视图(仿MJRefresh)
  3. OutOfMemoryException异常解析
  4. 程序员须知:必须建立个人知识库,它的重要性你需要了解一下!
  5. 记一次FFMPEG转avi视频保存到ftp服务器的失败尝试
  6. 使用Facelets开发JSF程序
  7. 翻译:响应式编程或反应式编程 RxSwift和RxCocoa 从入门到精通 Reactive programming
  8. WEBMAX函数 动态模糊特效【官方教程】
  9. 肿瘤全外显子--记录
  10. Cocos2d-X 3.x的具体配置详解
  11. Android Studio 报错记录
  12. 赶快来了解一下职场达人进化论吧,它都有哪些实战技巧?
  13. 一份职业游戏3D建模师日常工作流程列表,看完不信还有人说建模门槛低
  14. [DB][mysql]下出现 java.sql.SQLException: Incorrect string value: '\xF4\x80\x8E\xAE\xE8\x83...'
  15. 技术从业者的未来(三)
  16. 川崎机器人 AS语言基础运动指令表
  17. 面向特定问题的开源算法管理和推荐(六)
  18. Flutter开发之——下拉刷新
  19. USB2.0传输带宽
  20. Cadence Allegro(15):设置全局铜皮参数

热门文章

  1. 【Spark】Spark Quick Start(快速入门翻译)
  2. SQL学习之ucase()函数
  3. 5G NR MCG,SCG,PCell,PSCell,SCell,sPCell 概念
  4. 台式计算机对比评测报告,高效稳定的办公之选-宏碁商祺X4270评测报告
  5. http://blog.sina.com.cn/s/blog_ad1c3bdf0102uz99.html
  6. 润乾报表CookBook与使用
  7. 李春华:B2C商城做SEO的九个常见目标定位
  8. mac系统恢复服务器上的安装器损坏,Mac提示App已损坏你应该将它移到废纸篓的解决方案-mac无法安装软件解决教程 - 河东软件园...
  9. 每日写题分享--优先队列
  10. 清华大学出版社计算机绘谱,清华大学出版社-图书详情-《土木与建筑类CAD技能一级(二维计算机绘图)AutoCAD培训教程》...