Как я могу управлять своим TimerTask каждый день в 2 часа дня - PullRequest
32 голосов
/ 21 февраля 2012

Я хочу выполнять работу каждый день в 2 часа дня. Какой метод java.util.Timer я могу использовать для планирования своей работы?

После 2 часов работы он остановит работу и перенесет ее на следующий день. 2 вечера.

Ответы [ 9 ]

54 голосов
/ 07 августа 2013
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
22 голосов
/ 21 февраля 2012

Вы можете использовать метод Timer.schedule(TimerTask task, Date firstTime, long period), установив firstTime на 2 вечера сегодня и установив period на 24 часа:

Планирует указанную задачу для повторного выполнения с фиксированной задержкой, начиная с указанного времени. Последующие казни происходят примерно через равные промежутки времени, разделенные указанным периодом.

15 голосов
/ 21 февраля 2012
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();

    }

}
4 голосов
/ 21 февраля 2012

Самый простой способ сделать это всегда был через Task Scheduler в Windows и cron в Linux.

Однако для Java взгляните на Кварцевый планировщик

С их сайта:

Quartz - это полнофункциональная служба планирования заданий с открытым исходным кодом, которая может быть интегрированным или используемым вместе практически с любой Java EE или Java Приложение SE - от самого маленького автономного приложения до крупнейшая система электронной коммерции. Кварц можно использовать для создания простых или сложные графики для выполнения десятков, сотен или даже десятки тысяч рабочих мест; задания, задачи которых определены как стандартные Компоненты Java, которые могут выполнять практически все, что вы можете программировать им делать. Кварцевый планировщик включает в себя много корпоративного класса такие функции, как транзакции JTA и кластеризация.

3 голосов
/ 21 февраля 2012

Вы должны попробовать использовать scheduleAtFixedRate (это будет повторять вашу задачу). Вам нужно будет создать объект TimerTask, который будет указывать, что запускать (в run ()) и когда запускать (scheduleExecutionTime). scheduleAtFixedRate также позволяет указать первую дату исполнения.

2 голосов
/ 13 июля 2016

Почему бы вам не использовать Spring's @Scheduled (cron = "0 0 14 * * *") .. для сек, мин, часов, дня, месяца, дняOfWeek. V Круто. Вы можете даже указать 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 и предоставьте @EnableScheduling в классе Application.java (класс содержит основной метод), чтобы Spring осознал, что вы используете taskcheduler в вашем приложении.

1 голос
/ 02 сентября 2018

Большинство ответов на этот вопрос и следующие два вопроса предполагают, что миллисекунды в день всегда одинаковы .
Как запланировать периодическое задание в 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));

Основная идея кода заключается в следующем:пересчитать оставшееся время до следующего тика и каждый раз запускать новый таймер.

1 голос
/ 21 августа 2018

Срок исполнения java.util.Timer :

Java 5.0 представила пакет java.util.concurrent и один из утилиты параллелизма в нем - ScheduledThreadPoolExecutor, который пул потоков для многократного выполнения задач с заданной скоростью или задержка. Это фактически более универсальная замена для Комбинация Timer / TimerTask, так как она позволяет использовать несколько потоков услуг, принимает различные единицы времени и не требует создания подклассов TimerTask (просто реализовать Runnable). Настройка ScheduledThreadPoolExecutor с одним потоком делает его эквивалентным Таймеру.

Итак (добавьте этот код в свой класс):

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);

    }  
1 голос
/ 21 февраля 2012

использовать общедоступное расписание void (задача TimerTask, дата firstTime, длительный период)

, чтобы повторять задачу на следующий день, просто установите период равным 86400000 миллисекунд (что означает 1 день)

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

Timer timer = new Timer();

timer.sc(myOwnTimerTask,date2pm, 86400000);
...