定时任务

1.java时间格式使用

class Example {
public static void main(String args[]) {
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));//定义时区,可以避免虚拟机时间与系统时间不一致的问题

System.out.println(new Date(System.currentTimeMillis()));//方法一:默认方式输出现在时间

Date nowTime = new Date();
System.out.println(nowTime);//方法二:Date方式,输出现在时间

SimpleDateFormat matter = new SimpleDateFormat(
"现在时间:yyyy年MM月dd日E HH时mm分ss秒");
System.out.println(matter.format(nowTime));//方法三:SimpleDateFormat方式,完整输出现在时间
}

jvm时间和系统时间不一致,大体可能是一下几种情况:
①现象:相差时间整数小时,但不超过24小时。原因:jvm设置的时区不正确,或者启用了夏时令(IBM产品),具体在那里设置需要看使用的是什么APL服务器。
②现象:相差非整数小时。某种条件下,JVM中读取系统时间的时候,是在应用程序启动之后,读一次OS的系统时间,然后JVM中根据CPU ticks来自己计算时间,而不是实时地去OS 取系统时间。这样的话,在应用程序运行当中,如果改变了OS的系统时间,那么JVM和OS的系统时间就不一致了。

 

常用的时间格式(DateFormat工具,SimpleDateFormat,Canlendar)

public class showDate {    

    public static void main(String[] args) throws ParseException {    

    

        Date d = new Date();    

        String s = null;    

    

        /** 输出格式: Mon May 05 15:23:58 CST 2014 */    

        System.out.println(d);    

    

        /** 输出格式: 2014-5-5 */    

        s = DateFormat.getDateInstance().format(d);    

        System.out.println(s);    

    

        /** 输出格式: 2014-5-5 */    

        s = DateFormat.getDateInstance(DateFormat.DEFAULT).format(d);    

        System.out.println(s);    

    

        /** 输出格式: 2014年5月5日 星期一 */    

        s = DateFormat.getDateInstance(DateFormat.FULL).format(d);    

        System.out.println(s);    

    

        /** 输出格式: 2014-5-5 */    

        s = DateFormat.getDateInstance(DateFormat.MEDIUM).format(d);    

        System.out.println(s);    

    

        /** 输出格式: 14-5-5 */    

        s = DateFormat.getDateInstance(DateFormat.SHORT).format(d);    

        System.out.println(s);    

    

        /** 输出格式: 2014-5-05 00:00:00 大写H为24小时制 */    

        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    

        s = sdf.format(d);    

        System.out.println(s);    

    

        /** 输出格式: 2014-5-05 00:00:00 小写h为12小时制 */    

        DateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");    

        s = sdf2.format(d);    

        System.out.println(s);    

    

        /** 输出格式: 20140505000000 */    

        DateFormat sdf3 = new SimpleDateFormat("yyyyMMddHHmmss");    

        s = sdf3.format(d);    

        System.out.println(s);    

    

        /** 字符串转换城日期格式 */    

        s = sdf.format(d);    

        Date today = sdf.parse(s);    

        System.out.println("字符串转成日期1:" + today);    

        System.out.println("字符串转成日期2:" + sdf.format(today));    

    

        /** 单独输出年月日时分秒等 */    

        Calendar c = Calendar.getInstance();    

        System.out.println("年: " + c.get(Calendar.YEAR));    

        // 月份从0开始,加1校正    

        System.out.println("月: " + (c.get(Calendar.MONTH) + 1) + "");    

        System.out.println("日: " + c.get(Calendar.DAY_OF_MONTH));    

        System.out.println("时: " + c.get(Calendar.HOUR_OF_DAY));    

        System.out.println("分: " + c.get(Calendar.MINUTE));    

        System.out.println("秒: " + c.get(Calendar.SECOND));    

        System.out.println("当前时间毫秒数:" + c.getTimeInMillis());    

        System.out.println("当前时间: " + c.getTime());    

    }    

}    

2.内部类文章 

http://www.cnblogs.com/dolphin0520/p/3811445.html

3.定时任务实现

3.1使用java线程实现

借用线程的sleep实现方法每隔指定时间执行,缺点:功能过于简单不灵活,线程需要挂起浪费资源,当需要多个任务的时候尤为突出。

 

 

3.2 使用TimeTask Timer

比较下schedule和scheduleAtFixedRate两个方法:

schedule(TimerTask task, Date firstTime, long period)、schedule(TimerTask task, long delay, long period)

这两个方法与上面两个就有点儿不同的,前面提过Timer的计时器任务会因为前一个任务执行时间较长而延时。在这两个方法中,每一次执行的task的计划时间会随着前一个task的实际时间而发生改变,也就是scheduledExecutionTime(n+1)=realExecutionTime(n)+periodTime。也就是说如果第n个task由于某种情况导致这次的执行时间过程,最后导致systemCurrentTime>= scheduledExecutionTime(n+1),这是第n+1个task并不会因为到时了而执行,他会等待第n个task执行完之后再执行,那么这样势必会导致n+2个的执行实现scheduledExecutionTime放生改变即scheduledExecutionTime(n+2) = realExecutionTime(n+1)+periodTime。所以这两个方法更加注重保存间隔时间的稳定。

scheduleAtFixedRate(TimerTask task, Date firstTime, long period)、scheduleAtFixedRate(TimerTask task, long delay, long period)

在前面也提过scheduleAtFixedRate与schedule方法的侧重点不同,schedule方法侧重保存间隔时间的稳定,而scheduleAtFixedRate方法更加侧重于保持执行频率的稳定。为什么这么说,原因如下。在schedule方法中会因为前一个任务的延迟而导致其后面的定时任务延时,而scheduleAtFixedRate方法则不会,如果第n个task执行时间过长导致systemCurrentTime>= scheduledExecutionTime(n+1),则不会做任何等待他会立即执行第n+1个task,所以scheduleAtFixedRate方法执行时间的计算方法不同于schedule,而是scheduledExecutionTime(n)=firstExecuteTime +n*periodTime,该计算方法永远保持不变。所以scheduleAtFixedRate更加侧重于保持执行频率的稳定。

 

 scheduleAtFixedRate如果超过当前时间会立即执行多次任务,而且执行的时间基于当前时间和间隔计算都是固定的,schedule则和任务执行时间有关系~~是任务执行时间+间隔

timer.schedule(f,date,10000);

timer.scheduleAtFixedRate(f, date, 10000);

 

里需要注意两个问题:

  if (mTimerTask != null){
           mTimerTask.cancel();  //将原任务从队列中移除
      }

每次放定时任务前,确保之前任务已从定时器队列中移除

 mTimerTask = new MyTimerTask();  // 新建一个任务      

每次放任务都要新建一个对象,否则出现一下错误:
 ERROR/AndroidRuntime(11761): java.lang.IllegalStateException: TimerTask is scheduled already
  所以同一个定时器任务只能被放置一次

3.3 使用ScheduledThreadPoolExecutor

 Timer是基于绝对时间的。容易受系统时钟的影响。 
b. Timer只新建了一个线程来执行所有的TimeTask。所有TimeTask可能会相关影响,单线程任务。 
c. Timer不会捕获TimerTask的异常,只是简单地停止。这样势必会影响其他TimeTask的执行。 

如果你是使用JDK1.5以上版本,建议用ScheduledThreadPoolExecutor代替Timer。它基本上解决了上述问题。它采用相对时间,用线程池来执行TimerTask,会出来TimerTask异常。 

 

posted on 2017-10-10 11:16  小付瓜  阅读(94)  评论(0)    收藏  举报