如何安排任务定期运行?

时间:2010-12-28 06:44:56

标签: java timer schedule

我正在尝试使用一些代码来实现计划任务,并提出了这些代码。

import java.util.*;

class Task extends TimerTask {


    int count = 1;

    // run is a abstract method that defines task performed at scheduled time.
    public void run() {
        System.out.println(count+" : Mahendra Singh");
        count++;
    }
}

class TaskScheduling {

   public static void main(String[] args) {
       Timer timer = new Timer();


       // Schedule to run after every 3 second(3000 millisecond)
       timer.schedule( new Task(), 3000);   
   }
}

我的输出:

1  :  Mahendra Singh

我希望编译器能够以3秒的周期间隔打印一系列Mahendra Singh,但是等待大约15分钟后,我只得到一个输出......我该如何解决这个问题?

6 个答案:

答案 0 :(得分:74)

ScheduledExecutorService超过Timer

的优势

我希望为您提供Timer使用 - ScheduledThreadPoolExecutor的替代方案,ScheduledExecutorService接口的实现。根据“Java in Concurrency”:

,它比Timer类有一些优势
  

Timer只创建一个用于执行计时器任务的线程。如果一个   定时器任务运行时间太长,其他的定时精度   TimerTask会受到影响。如果计划重复运行TimerTask   每隔10毫秒,另一个Timer-Task需要40毫秒才能运行,反复出现   任务(取决于它是按固定费率安排还是   固定延迟)之后快速连续四次被调用   长时间运行的任务完成,或完全“错过”四个调用。   计划的线程池通过允许您提供来解决此限制   用于执行延迟和定期任务的多个线程。

Timer的另一个问题是,如果TimerTask 引发未经检查的异常,则表现不佳。另外,称为“线程泄漏”

  

Timer线程没有捕获异常,因此未经检查   从TimerTask抛出的异常终止计时​​器线程。计时器   在这种情况下也不会复活线程;相反,它   错误地假设整个计时器被取消。在这种情况下,   从未调度但尚未执行的TimerTasks   运行,无法安排新任务。

另外一条建议是,如果您需要构建自己的调度服务,您仍然可以使用DelayQueueBlockingQueue实现来提供{的调度功能,从而利用该库。 {1}}。 ScheduledThreadPoolExecutor管理一组Delayed对象。延迟具有与之关联的延迟时间:DelayQueue允许您仅在其延迟已过期时获取元素。对象按照与其延迟相关联的时间排序的DelayQueue返回。

答案 1 :(得分:67)

使用timer.scheduleAtFixedRate

public void scheduleAtFixedRate(TimerTask task,
                                long delay,
                                long period)

在指定的延迟之后开始,为重复的固定速率执行计划指定的任务。随后的执行大约定期进行,并按指定的时间段分开     在固定速率执行中,每次执行都是相对于初始执行的预定执行时间进行调度的。如果由于任何原因(例如垃圾收集或其他后台活动)延迟执行,则会快速连续执行两次或更多次执行以“赶上”。从长远来看,执行频率将恰好是指定周期的倒数(假设Object.wait(long)下的系统时钟是准确的)。

固定费率执行适用于对绝对时间敏感的重复活动,例如每小时按小时响铃,或在特定时间每天运行定期维护。它也适用于重复活动,其中执行固定执行次数的总时间很重要,例如倒计时器,每秒钟滴答一次,持续十秒钟。最后,固定速率执行适用于调度必须保持彼此同步的多个重复计时器任务。

参数:

  • 任务 - 要安排的任务。
  • 延迟 - 执行任务前的延迟(以毫秒为单位)。
  • 时间段 - 连续任务执行之间的时间(以毫秒为单位)。

抛出:

  • IllegalArgumentException - 如果延迟为负数,或者延迟+ System.currentTimeMillis()为负数。
  • IllegalStateException - 如果已安排或取消任务,取消计时器或终止计时器线程。

答案 2 :(得分:14)

public void schedule(TimerTask task,long delay)

在指定的延迟后安排指定的任务执行。

你想要:

public void schedule(TimerTask task, long delay, long period)

在指定的延迟之后开始,为重复的固定延迟执行计划指定的任务。随后的执行大约以规定的时间间隔进行,并按指定的时间段分开。

答案 3 :(得分:4)

Quartz调度程序也是一个解决方案,首先你可以创建Quartz Job类。

Quartz作业定义了您要运行的内容

package com.blogspot.geekonjava.quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
public class QuartzJob implements Job {
        public void execute(JobExecutionContext context)
                        throws JobExecutionException {
                JobKey jobKey = context.getJobDetail().getKey();
                System.out.println("Quartz" + "Job Key " + jobKey);
        }
}

现在你需要做 Quartz Trigger

Quartz中有两种类型的触发器

SimpleTrigger - 允许设置开始时间,结束时间,重复间隔。

Trigger trigger = newTrigger().withIdentity("TriggerName", "Group1")
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10).repeatForever()).build();

CronTrigger - 允许Unix cron表达式指定日期和         时间来完成你的工作。

Trigger trigger = newTrigger()
                .withIdentity("TriggerName", "Group2")
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();

计划程序类将作业触发器链接在一起并执行它。

Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);

<强> Full Example you can see here

答案 4 :(得分:2)

timer.scheduleAtFixedRate( new Task(), 1000,3000); 

答案 5 :(得分:1)

为此,Java有Timer和TimerTask类但它是什么?

  • java.util.Timer 是一个可用于计划安排的实用程序类 线程将来某个时间执行。 Java Timer类可以 用于安排一次性运行或定期运行的任务 间隔。
  • java.util.TimerTask 是一个实现的抽象类 Runnable接口,我们需要扩展这个类来创建我们自己的 可以使用java Timer类调度的TimerTask。

您可以查看 GeekonJava

中的完整教程
TimerTask timerTask = new MyTimerTask();

//running timer task as daemon thread

Timer timer = new Timer(true);

timer.scheduleAtFixedRate(timerTask, 0, 10*1000);