码迷,mamicode.com
首页 > 编程语言 > 详细

Java 实现定时器ScheduledThreadPoolExecutor

时间:2015-08-14 06:36:14      阅读:367      评论:0      收藏:0      [点我收藏+]

标签:

Java 实现定时器ScheduledThreadPoolExecutor

延迟任务:在100秒后执行该任务

周期任务:每10秒执行一次任务

Timer存在一些缺陷,应该考虑使用ScheduleThreadPoolExecutor 来代替他。

可以通过ScheduleThreadPoolExecutor 的构造函数或Executors 的 newScheduleThreadPool  工厂方法来创建该类的对象。

Timer在执行所有定时任务时只会创建一个线程。如果某个任务执行时间过长,那么将破坏其他TimerTask的定时精确性。

Timer另一个问题是如果TimeTask抛出了一个未检查的异常,那么Timer将表现出槽糕的行为。Timer线程并不捕获异常,因此

当TimerTask抛出未检查的异常时将终止定时线程。这种情况下,Timer也不会恢复线程的执行,而是会错误地认为整个Timer都消失了。

因此,已经被调度但尚未执行的TimerTask将不会再执行,新的任务也不会被调度。这就是线程泄漏。


ScheduledThreadPoolExecutor继承结构

技术分享


延迟和周期任务的执行

如下代码片段

package com.usoft.schedule;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author: Lenovo(2015-08-13 23:54)
 */
public class ScheduledTest {

    public static void main(String args[]) throws ExecutionException, InterruptedException {
        ScheduledExecutorService schedule = Executors
                .newScheduledThreadPool(2);

        /**
         * 延迟1秒执行任务一次
         */
        schedule.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world runnable");
            }
        }, 1000, TimeUnit.MILLISECONDS);


        /**
         * 延迟2秒执行任务一次
         */
        Future result = schedule.schedule(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "hello world callable";
            }
        }, 2000, TimeUnit.MILLISECONDS);

        System.out.println(result.get());

        // 以固定的频率来周期的执行任务
        schedule.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("定时周期任务执行");
            }
        }, 1000, 2000, TimeUnit.MILLISECONDS);


        // 以固定的延迟来周期的执行任务
        schedule.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                System.out.println("定时周期任务执行");
            }
        }, 1000, 3000, TimeUnit.MILLISECONDS);

        // 关闭定时和周期任务的执行
        Thread.sleep(1000 * 10);
        schedule.shutdown();
        System.out.println("pool shutdown:" + schedule.isShutdown());
        while (!schedule.isTerminated()) {
            schedule.awaitTermination(1, TimeUnit.SECONDS);
        }
    }
}


定时任务的执行

要说定时任务,其实都是用延迟任务和周期任务来实现定时的。

比如说,我要在每天的中午12点启动一个定时任务,就要根据当前程序的启动时间来算出延迟多长时间来执行这个任务,并且是周期的执行,有一个固定的算法来算出延迟的时长。

package com.usoft.schedule;

import java.util.Calendar;

public class Main23 {

    private static final int period = 1000 * 60; //秒
    private static final int one_day_millseconds = 24 * 60 * 60 * 1000;

    public static void main(String args[]) {
        int dayOfHour = 0; // 24h 制
        int minute = 0;
        int second = 0;
        long delay;  //首次执行任务的延迟
        Calendar c = Calendar.getInstance();
        long currentTime = c.getTimeInMillis();
        c.set(Calendar.HOUR_OF_DAY, dayOfHour);
        c.set(Calendar.MINUTE, minute);
        c.set(Calendar.SECOND, second);
        long executeTime = c.getTimeInMillis();
        delay = executeTime - currentTime < 0 ? (executeTime - currentTime + one_day_millseconds)
            : (executeTime - currentTime);
        System.out.println("DelayTimeInMillis =" + delay);
        System.out.println("DelayTimeInSecond =" + delay / 1000);
        System.out.println("DelayTimeInHour =" + delay / (1000 * 60 * 60));
    }
}

这里简单的指定小时分钟和秒,也就说当到了这个时刻就要周期的执行这个任务。那么要延迟多长时间执行这个任务就可以根据以上代码来算出来。

也可以选择不是周期的执行任务,只是在这个时刻执行一次任务。

====================END====================

Java 实现定时器ScheduledThreadPoolExecutor

标签:

原文地址:http://my.oschina.net/xinxingegeya/blog/492110

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!