如何每天下午 2 点运行 TimerTask?

发布于 2025-01-07 18:46:52 字数 98 浏览 0 评论 0原文

我想每天下午 2 点执行一项工作。我可以使用 java.util.Timer 的哪种方法来安排我的工作?

2 小时后,运行它将停止作业并重新安排到第二天下午 2 点。

I want to execute a job everyday 2PM. Which method of java.util.Timer I can use to schedule my job?

After 2Hrs, run it will stop the job and reschedule for next day 2PM.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

深空失忆 2025-01-14 18:46:52
Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, 2);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);

// every night at 2am you run your task
Timer timer = new Timer();
timer.schedule(new YourTask(), today.getTime(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS)); // period: 1 day
Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, 2);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);

// every night at 2am you run your task
Timer timer = new Timer();
timer.schedule(new YourTask(), today.getTime(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS)); // period: 1 day
凉栀 2025-01-14 18:46:52

您可以使用 Timer.schedule(TimerTask task, Date firstTime, long period) 方法,将 firstTime 设置为今天下午 2 点,并将 period 设置为24小时:

安排指定任务从指定时间开始重复固定延迟执行。随后的执行大约以固定的时间间隔进行,并以指定的时间段分隔。

You could use Timer.schedule(TimerTask task, Date firstTime, long period) method, setting firstTime to 2PM today and the setting the period to 24-hours:

Schedules the specified task for repeated fixed-delay execution, beginning at the specified time. Subsequent executions take place at approximately regular intervals, separated by the specified period.

青朷 2025-01-14 18:46:52
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;


public class MyTimerTask extends TimerTask {
    private final static long ONCE_PER_DAY = 1000*60*60*24;

    //private final static int ONE_DAY = 1;
    private final static int TWO_AM = 2;
    private final static int ZERO_MINUTES = 0;


    @Override
    public void run() {
        long currennTime = System.currentTimeMillis();
        long stopTime = currennTime + 2000;//provide the 2hrs time it should execute 1000*60*60*2
          while(stopTime != System.currentTimeMillis()){
              // Do your Job Here
            System.out.println("Start Job"+stopTime);
            System.out.println("End Job"+System.currentTimeMillis());
          }
    }
    private static Date getTomorrowMorning2AM(){

        Date date2am = new java.util.Date(); 
           date2am.setHours(TWO_AM); 
           date2am.setMinutes(ZERO_MINUTES); 

           return date2am;
      }
    //call this method from your servlet init method
    public static void startTask(){
        MyTimerTask task = new MyTimerTask();
        Timer timer = new Timer();  
        timer.schedule(task,getTomorrowMorning2AM(),1000*10);// for your case u need to give 1000*60*60*24
    }
    public static void main(String args[]){
        startTask();

    }

}
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;


public class MyTimerTask extends TimerTask {
    private final static long ONCE_PER_DAY = 1000*60*60*24;

    //private final static int ONE_DAY = 1;
    private final static int TWO_AM = 2;
    private final static int ZERO_MINUTES = 0;


    @Override
    public void run() {
        long currennTime = System.currentTimeMillis();
        long stopTime = currennTime + 2000;//provide the 2hrs time it should execute 1000*60*60*2
          while(stopTime != System.currentTimeMillis()){
              // Do your Job Here
            System.out.println("Start Job"+stopTime);
            System.out.println("End Job"+System.currentTimeMillis());
          }
    }
    private static Date getTomorrowMorning2AM(){

        Date date2am = new java.util.Date(); 
           date2am.setHours(TWO_AM); 
           date2am.setMinutes(ZERO_MINUTES); 

           return date2am;
      }
    //call this method from your servlet init method
    public static void startTask(){
        MyTimerTask task = new MyTimerTask();
        Timer timer = new Timer();  
        timer.schedule(task,getTomorrowMorning2AM(),1000*10);// for your case u need to give 1000*60*60*24
    }
    public static void main(String args[]){
        startTask();

    }

}
浅唱々樱花落 2025-01-14 18:46:52

我发现执行此操作的最简单方法始终是通过 Windows 中的任务计划程序和 Linux 中的 cron。

然而,对于 Java,请查看 Quartz Scheduler

从他们的网站:

Quartz 是一个功能齐全的开源作业调度服务,可以
与几乎任何 Java EE 或 Java 集成或一起使用
SE 应用程序 - 从最小的独立应用程序到
最大的电子商务系统。石英可用于创建简单或
执行数十、数百甚至什至的复杂计划
数以万计的工作岗位;任务被定义为标准的工作
Java 组件几乎可以执行您可以编写的任何内容
他们要做的事。 Quartz Scheduler包含许多企业级的
功能,例如 JTA 事务和集群。

The easiest way I've found of doing this has always been through Task Scheduler in Windows and cron in Linux.

However for Java, take a look at Quartz Scheduler

From their website:

Quartz is a full-featured, open source job scheduling service that can
be integrated with, or used along side virtually any Java EE or Java
SE application - from the smallest stand-alone application to the
largest e-commerce system. Quartz can be used to create simple or
complex schedules for executing tens, hundreds, or even
tens-of-thousands of jobs; jobs whose tasks are defined as standard
Java components that may execute virtually anything you may program
them to do. The Quartz Scheduler includes many enterprise-class
features, such as JTA transactions and clustering.

自此以后,行同陌路 2025-01-14 18:46:52

此问题和以下两个问题的大多数答案假设每天的毫秒数始终相同
如何在 Java 中安排周期性任务?
如何运行特定任务使用 ScheduledExecutorService 确定一天中的特定时间?

但是,由于夏令时和闰秒,这不是真的。
这意味着如果您的服务已存在多年并且计时器的准确性很重要,
固定周期计时器不是您的选择。

因此,我想介绍一个比 java.util.Timer 更灵活的计时器的代码片段。

package szx;
    
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.function.Function;
    
public class ScheduledExecutor {
  public void scheduleRegularly(Runnable task, LocalDateTime firstTime,
                                Function<LocalDateTime, LocalDateTime> nextTime) {
    pendingTask = task;
    scheduleRegularly(firstTime, nextTime);
  }

  protected void scheduleRegularly(LocalDateTime firstTime,
                                   Function<LocalDateTime, LocalDateTime> nextTime) {
    new Timer().schedule(new TimerTask() {
      @Override
      public void run() {
        scheduleRegularly(nextTime.apply(firstTime), nextTime);
        pendingTask.run();
      }
    }, Date.from(firstTime.atZone(ZoneId.systemDefault()).toInstant()));
  }

  private volatile Runnable pendingTask = null;
}

然后,您可以通过以下方式调用上述方法来执行每天下午 2 点的作业。

new ScheduledExecutor().scheduleRegularly(() -> {

    // do your task...

}, LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).withHour(14), thisTime -> thisTime.plusDays(1));

代码背后的基本思想是重新计算到下一个tick的剩余时间并每次启动一个新的计时器。

Most answers for this question and the following two questions assume that the milliseconds per day is always the same.
How to schedule a periodic task in Java?
How to run certain task every day at a particular time using ScheduledExecutorService?

However, it's not ture due to day lights saving and leap seconds.
This means that if your service is alive for years and the accuracy of the timer matters,
a fixed period timer is not your choice.

So, I'd like to introduce my code snippet for a more flexible timer than the java.util.Timer.

package szx;
    
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.function.Function;
    
public class ScheduledExecutor {
  public void scheduleRegularly(Runnable task, LocalDateTime firstTime,
                                Function<LocalDateTime, LocalDateTime> nextTime) {
    pendingTask = task;
    scheduleRegularly(firstTime, nextTime);
  }

  protected void scheduleRegularly(LocalDateTime firstTime,
                                   Function<LocalDateTime, LocalDateTime> nextTime) {
    new Timer().schedule(new TimerTask() {
      @Override
      public void run() {
        scheduleRegularly(nextTime.apply(firstTime), nextTime);
        pendingTask.run();
      }
    }, Date.from(firstTime.atZone(ZoneId.systemDefault()).toInstant()));
  }

  private volatile Runnable pendingTask = null;
}

Then, you can execute your job everyday 2PM by invoking the above method in the following way.

new ScheduledExecutor().scheduleRegularly(() -> {

    // do your task...

}, LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).withHour(14), thisTime -> thisTime.plusDays(1));

The basic idea behind the code is to recalculate the left time to the next tick and start a new timer every time.

墨落成白 2025-01-14 18:46:52

您应该尝试使用scheduleAtFixedRate(这将重复您的任务)。您将需要创建一个 TimerTask 对象,该对象将指定要运行的内容(在 run() 中)以及何时运行(scheduledExecutionTime)。 ScheduleAtFixedRate 还允许您指定第一个执行日期。

You should try using scheduleAtFixedRate (this will repeat your task). You will need to create an TimerTask object which will specify what to run (in run()) and when to run (scheduledExecutionTime). scheduleAtFixedRate also allows you to specify the first date of execution.

情仇皆在手 2025-01-14 18:46:52

你为什么不使用 Spring 的 @Scheduled(cron="0 0 14 * * *") .. 秒、分、小时、日、月、dayOfWeek。酷。您甚至可以在最后一个参数中指定 9-11 表示 9:00 到 11:00,或 MON-FRI。
如果您想在运行时设置时间,您也可以以编程方式调用它,就像大多数 Spring 的情况一样。
看看这个:-
http://docs.spring.io/ spring/docs/current/spring-framework-reference/html/scheduling.html

添加一个示例

   @Scheduled(cron="0 0 14 * * *")
    public void customScheduler(){
        try{
            // do what ever you want to run repeatedly
        }catch(Exception e){
            e.printStackTrace();

        }
    }

,也请使用 @Component 注释来注释包含此示例的类,并请在 Application.java 中提供 @EnableScheduling (类包含主要方法)类到让 spring 知道您正在应用程序中使用taskscheduler。

Why don't you use Spring's @Scheduled(cron="0 0 14 * * *") .. for sec, min, hours, day, month, dayOfWeek. V Cool. You can even specify 9-11 for 9:00 to 11:00, or MON-FRI in last parameter.
You can invoke this programatically too, like is case of most of Spring, in case you want to set the time at runtime.
See this:-
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

Adding an example

   @Scheduled(cron="0 0 14 * * *")
    public void customScheduler(){
        try{
            // do what ever you want to run repeatedly
        }catch(Exception e){
            e.printStackTrace();

        }
    }

also please annotate the class containing this with @Component annotation and please provide @EnableScheduling in the Application.java (class contains the main method) class to make spring aware that you are using taskscheduler in your applicaiton.

勿忘心安 2025-01-14 18:46:52

使用 public void Schedule(TimerTask task,Date firstTime,long period)

使任务在第二天再次重复,只需将 period 设置为 86400000 毫秒(即 1 天)

Date date2pm = new java.util.Date();
date2pm.setHour(14);
date2pm.setMinutes(0);

Timer timer = new Timer();

timer.sc(myOwnTimerTask,date2pm, 86400000);

use public void schedule(TimerTask task,Date firstTime,long period)

to make the task repeats again the next day, just set period to 86400000 milliseconds ( which means 1 day )

Date date2pm = new java.util.Date();
date2pm.setHour(14);
date2pm.setMinutes(0);

Timer timer = new Timer();

timer.sc(myOwnTimerTask,date2pm, 86400000);
不必在意 2025-01-14 18:46:52

由于 java.util.Timer

Java 5.0 引入了 java.util.concurrent 包和其中之一
其中的并发实用程序是 ScheduledThreadPoolExecutor,它
是一个以给定速率重复执行任务的线程池或
延迟。它实际上是一种更通用的替代品
Timer/TimerTask 组合,因为它允许多个服务线程,
接受各种时间单位,并且不需要子类化 TimerTask
(只需实现 Runnable)。配置 ScheduledThreadPoolExecutor
一个线程相当于Timer。

所以(将此代码添加到您的类中):

private ScheduledExecutorService scheduledExecutorService;

    public ScheduledSendLog() {
        init();
    }

    public void destroy() {
        this.scheduledExecutorService.shutdown();
    }

    private void init() {
        scheduledExecutorService =
                Executors.newScheduledThreadPool(1);
        System.out.println("---ScheduledSendLog created " + LocalDateTime.now());
        startSchedule(LocalTime.of(02, 00));
    }


    private void startSchedule(LocalTime atTime) {
        this.scheduledExecutorService.scheduleWithFixedDelay(() -> {
                    System.out.println(Thread.currentThread().getName() +
                            " |  scheduleWithFixedDelay | " + LocalDateTime.now());
                    // or whatever you want
                }, calculateInitialDelayInSec(atTime),
                LocalTime.MAX.toSecondOfDay(),
                TimeUnit.SECONDS);
    }

    private long calculateInitialDelayInSec(LocalTime atTime) {
        int currSec = LocalTime.now().toSecondOfDay();
        int atSec = atTime.toSecondOfDay();
        return (currSec < atSec) ?
                atSec - currSec : (LocalTime.MAX.toSecondOfDay() + atSec - currSec);

    }  

Due java.util.Timer:

Java 5.0 introduced the java.util.concurrent package and one of the
concurrency utilities therein is the ScheduledThreadPoolExecutor which
is a thread pool for repeatedly executing tasks at a given rate or
delay. It is effectively a more versatile replacement for the
Timer/TimerTask combination, as it allows multiple service threads,
accepts various time units, and doesn't require subclassing TimerTask
(just implement Runnable). Configuring ScheduledThreadPoolExecutor
with one thread makes it equivalent to Timer.

so (add this code to your class):

private ScheduledExecutorService scheduledExecutorService;

    public ScheduledSendLog() {
        init();
    }

    public void destroy() {
        this.scheduledExecutorService.shutdown();
    }

    private void init() {
        scheduledExecutorService =
                Executors.newScheduledThreadPool(1);
        System.out.println("---ScheduledSendLog created " + LocalDateTime.now());
        startSchedule(LocalTime.of(02, 00));
    }


    private void startSchedule(LocalTime atTime) {
        this.scheduledExecutorService.scheduleWithFixedDelay(() -> {
                    System.out.println(Thread.currentThread().getName() +
                            " |  scheduleWithFixedDelay | " + LocalDateTime.now());
                    // or whatever you want
                }, calculateInitialDelayInSec(atTime),
                LocalTime.MAX.toSecondOfDay(),
                TimeUnit.SECONDS);
    }

    private long calculateInitialDelayInSec(LocalTime atTime) {
        int currSec = LocalTime.now().toSecondOfDay();
        int atSec = atTime.toSecondOfDay();
        return (currSec < atSec) ?
                atSec - currSec : (LocalTime.MAX.toSecondOfDay() + atSec - currSec);

    }  
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文