Làm cách nào để chạy một số tác vụ nhất định hàng ngày vào một thời điểm cụ thể bằng SchedisedExecutorService?


90

Tôi đang cố gắng thực hiện một công việc nhất định hàng ngày vào lúc 5 giờ sáng. Vì vậy, tôi quyết định sử dụng ScheduledExecutorServicecho điều này nhưng cho đến nay tôi đã thấy các ví dụ cho thấy cách chạy tác vụ sau mỗi vài phút.

Và tôi không thể tìm thấy bất kỳ ví dụ nào cho thấy cách thực hiện một công việc hàng ngày vào một thời điểm cụ thể (5 giờ sáng) vào buổi sáng và cũng xem xét thực tế về thời gian tiết kiệm ánh sáng ban ngày -

Dưới đây là mã của tôi sẽ chạy sau mỗi 15 phút -

public class ScheduledTaskExample {
    private final ScheduledExecutorService scheduler = Executors
        .newScheduledThreadPool(1);

    public void startScheduleTask() {
    /**
    * not using the taskHandle returned here, but it can be used to cancel
    * the task, or check if it's done (for recurring tasks, that's not
    * going to be very useful)
    */
    final ScheduledFuture<?> taskHandle = scheduler.scheduleAtFixedRate(
        new Runnable() {
            public void run() {
                try {
                    getDataFromDatabase();
                }catch(Exception ex) {
                    ex.printStackTrace(); //or loggger would be better
                }
            }
        }, 0, 15, TimeUnit.MINUTES);
    }

    private void getDataFromDatabase() {
        System.out.println("getting data...");
    }

    public static void main(String[] args) {
        ScheduledTaskExample ste = new ScheduledTaskExample();
        ste.startScheduleTask();
    }
}

Có cách nào để tôi có thể lên lịch tác vụ chạy hàng ngày 5 giờ sáng vào buổi sáng bằng cách sử dụng ScheduledExecutorServicecả thời gian tiết kiệm ánh sáng ban ngày không?

Và cũng TimerTasktốt hơn cho điều này hoặc ScheduledExecutorService?


Sử dụng một cái gì đó như Quartz để thay thế.
millimoose

Câu trả lời:


113

Như với bản phát hành java SE 8 hiện tại với API ngày giờ tuyệt vời của nó với java.timeloại tính toán này có thể được thực hiện dễ dàng hơn thay vì sử dụng java.util.Calendarjava.util.Date.

Bây giờ là một ví dụ mẫu để lên lịch tác vụ với ca sử dụng của bạn:

ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));
ZonedDateTime nextRun = now.withHour(5).withMinute(0).withSecond(0);
if(now.compareTo(nextRun) > 0)
    nextRun = nextRun.plusDays(1);

Duration duration = Duration.between(now, nextRun);
long initalDelay = duration.getSeconds();

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);            
scheduler.scheduleAtFixedRate(new MyRunnableTask(),
    initalDelay,
    TimeUnit.DAYS.toSeconds(1),
    TimeUnit.SECONDS);

initalDelayđược tính toán để yêu cầu bộ lập lịch trì hoãn việc thực thi trong TimeUnit.SECONDS. Các vấn đề chênh lệch thời gian với đơn vị mili giây trở xuống dường như không đáng kể đối với trường hợp sử dụng này. Nhưng bạn vẫn có thể sử dụng duration.toMillis()TimeUnit.MILLISECONDSđể xử lý các phép tính lập lịch trong mili giây.

Và cũng có thể TimerTask tốt hơn cho điều này hoặc SchedonedExecutorService?

KHÔNG: ScheduledExecutorService có vẻ tốt hơn TimerTask. StackOverflow đã có câu trả lời cho bạn .

Từ @PaddyD,

Bạn vẫn gặp sự cố, theo đó bạn cần phải khởi động lại quá trình này hai lần một năm nếu bạn muốn nó chạy vào đúng giờ địa phương. SchedAtFixedRate sẽ không cắt giảm nó trừ khi bạn hài lòng với cùng thời gian UTC cả năm.

Đúng như sự thật và @PaddyD đã đưa ra giải pháp thay thế (+1 cho anh ấy), tôi đang cung cấp một ví dụ làm việc với API thời gian ngày của Java8 với ScheduledExecutorService. Sử dụng chuỗi daemon rất nguy hiểm

class MyTaskExecutor
{
    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
    MyTask myTask;
    volatile boolean isStopIssued;

    public MyTaskExecutor(MyTask myTask$) 
    {
        myTask = myTask$;

    }

    public void startExecutionAt(int targetHour, int targetMin, int targetSec)
    {
        Runnable taskWrapper = new Runnable(){

            @Override
            public void run() 
            {
                myTask.execute();
                startExecutionAt(targetHour, targetMin, targetSec);
            }

        };
        long delay = computeNextDelay(targetHour, targetMin, targetSec);
        executorService.schedule(taskWrapper, delay, TimeUnit.SECONDS);
    }

    private long computeNextDelay(int targetHour, int targetMin, int targetSec) 
    {
        LocalDateTime localNow = LocalDateTime.now();
        ZoneId currentZone = ZoneId.systemDefault();
        ZonedDateTime zonedNow = ZonedDateTime.of(localNow, currentZone);
        ZonedDateTime zonedNextTarget = zonedNow.withHour(targetHour).withMinute(targetMin).withSecond(targetSec);
        if(zonedNow.compareTo(zonedNextTarget) > 0)
            zonedNextTarget = zonedNextTarget.plusDays(1);

        Duration duration = Duration.between(zonedNow, zonedNextTarget);
        return duration.getSeconds();
    }

    public void stop()
    {
        executorService.shutdown();
        try {
            executorService.awaitTermination(1, TimeUnit.DAYS);
        } catch (InterruptedException ex) {
            Logger.getLogger(MyTaskExecutor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Ghi chú:

  • MyTasklà một giao diện có chức năng execute.
  • Trong khi dừng ScheduledExecutorService, Luôn sử dụng awaitTerminationsau khi gọi shutdown: Luôn có khả năng tác vụ của bạn bị kẹt / bế tắc và người dùng sẽ đợi mãi mãi.

Ví dụ trước đây tôi đưa ra với Calender chỉ là một ý tưởng mà tôi đã đề cập, tôi tránh các vấn đề về tính toán thời gian chính xác và tiết kiệm ánh sáng ban ngày. Đã cập nhật giải pháp theo phàn nàn của @PaddyD


Cảm ơn bạn đã gợi ý, bạn có thể vui lòng giải thích chi tiết intDelayInHourcho tôi cách thức mà tôi sẽ thực hiện nhiệm vụ của mình lúc 5 giờ sáng không?
AKIWEB

Mục đích của aDate là gì?
José Andias,

Nhưng nếu bạn bắt đầu điều này tại HH: mm, nhiệm vụ sẽ được chạy lúc 05: mm thay vì 5 giờ sáng? Nó cũng không tính đến thời gian tiết kiệm ánh sáng ban ngày như OP yêu cầu. Ok nếu bạn khởi động nó ngay sau giờ hoặc nếu bạn hài lòng với bất kỳ khoảng thời gian nào từ 5 đến 6, hoặc nếu bạn không ngại khởi động lại ứng dụng vào nửa đêm hai lần một năm sau khi đồng hồ thay đổi. ...
PaddyD

2
Bạn vẫn gặp sự cố, theo đó bạn cần phải khởi động lại nó hai lần một năm nếu bạn muốn nó chạy vào đúng giờ địa phương. scheduleAtFixedRatesẽ không cắt giảm trừ khi bạn hài lòng với cùng thời gian UTC cả năm.
PaddyD

3
Tại sao ví dụ sau (thứ hai) kích hoạt thực hiện n lần hoặc cho đến khi thứ hai trôi qua? Mã không được giả sử để kích hoạt tác vụ một lần mỗi ngày?
krizajb 27/09/18

25

Trong Java 8:

scheduler = Executors.newScheduledThreadPool(1);

//Change here for the hour you want ----------------------------------.at()       
Long midnight=LocalDateTime.now().until(LocalDate.now().plusDays(1).atStartOfDay(), ChronoUnit.MINUTES);
scheduler.scheduleAtFixedRate(this, midnight, 1440, TimeUnit.MINUTES);

14
Để dễ đọc, tôi sẽ đề xuất TimeUnit.DAYS.toMinutes(1)thay vì "con số kỳ diệu" 1440.
philonous

Cảm ơn, Victor. Theo cách này cần phải khởi động lại hai lần một năm nếu tôi muốn nó chạy vào đúng giờ địa phương?
invzbl3

tỷ giá cố định không được thay đổi khi giờ địa phương thay đổi, sau khi được tạo, nó sẽ trở thành tỷ giá.
Victor

Tại sao điều này lại kích hoạt nhiệm vụ của tôi lúc 23:59:59?
krizajb

Để dễ đọc, tôi sẽ đề xuất 1 thay vì 1440 hoặc TimeUnit.DAYS.toMinutes (1), và sau đó sử dụng đơn vị thời gian TimeUnit.DAYS. ;-)
Kelly Denehy

7

Nếu bạn không có khả năng sử dụng Java 8, những điều sau đây sẽ làm những gì bạn cần:

public class DailyRunnerDaemon
{
   private final Runnable dailyTask;
   private final int hour;
   private final int minute;
   private final int second;
   private final String runThreadName;

   public DailyRunnerDaemon(Calendar timeOfDay, Runnable dailyTask, String runThreadName)
   {
      this.dailyTask = dailyTask;
      this.hour = timeOfDay.get(Calendar.HOUR_OF_DAY);
      this.minute = timeOfDay.get(Calendar.MINUTE);
      this.second = timeOfDay.get(Calendar.SECOND);
      this.runThreadName = runThreadName;
   }

   public void start()
   {
      startTimer();
   }

   private void startTimer();
   {
      new Timer(runThreadName, true).schedule(new TimerTask()
      {
         @Override
         public void run()
         {
            dailyTask.run();
            startTimer();
         }
      }, getNextRunTime());
   }


   private Date getNextRunTime()
   {
      Calendar startTime = Calendar.getInstance();
      Calendar now = Calendar.getInstance();
      startTime.set(Calendar.HOUR_OF_DAY, hour);
      startTime.set(Calendar.MINUTE, minute);
      startTime.set(Calendar.SECOND, second);
      startTime.set(Calendar.MILLISECOND, 0);

      if(startTime.before(now) || startTime.equals(now))
      {
         startTime.add(Calendar.DATE, 1);
      }

      return startTime.getTime();
   }
}

Nó không yêu cầu bất kỳ lib bên ngoài nào và sẽ tính đến việc tiết kiệm ánh sáng ban ngày. Đơn giản chỉ cần chuyển thời gian trong ngày bạn muốn chạy tác vụ dưới dạng một Calendarđối tượng và tác vụ dưới dạng a Runnable. Ví dụ:

Calendar timeOfDay = Calendar.getInstance();
timeOfDay.set(Calendar.HOUR_OF_DAY, 5);
timeOfDay.set(Calendar.MINUTE, 0);
timeOfDay.set(Calendar.SECOND, 0);

new DailyRunnerDaemon(timeOfDay, new Runnable()
{
   @Override
   public void run()
   {
      try
      {
        // call whatever your daily task is here
        doHousekeeping();
      }
      catch(Exception e)
      {
        logger.error("An error occurred performing daily housekeeping", e);
      }
   }
}, "daily-housekeeping");

NB tác vụ hẹn giờ chạy trong một luồng Daemon không được khuyến nghị để thực hiện bất kỳ IO nào. Nếu bạn cần sử dụng chuỗi Người dùng, bạn sẽ cần thêm một phương thức khác để hủy bộ đếm thời gian.

Nếu bạn phải sử dụng a ScheduledExecutorService, chỉ cần thay đổi startTimerphương thức thành như sau:

private void startTimer()
{
   Executors.newSingleThreadExecutor().schedule(new Runnable()
   {
      Thread.currentThread().setName(runThreadName);
      dailyTask.run();
      startTimer();
   }, getNextRunTime().getTime() - System.currentTimeMillis(),
   TimeUnit.MILLISECONDS);
}

Tôi không chắc chắn về hành vi nhưng bạn có thể cần một phương pháp dừng gọi shutdownNownếu bạn đi xuống ScheduledExecutorServicetuyến đường, nếu không ứng dụng của bạn có thể bị treo khi bạn cố gắng dừng nó.


Tôi có điểm số của bạn. +1 và cảm ơn bạn. Tuy nhiên, sẽ tốt hơn nếu chúng ta không sử dụng luồng Daemon (tức là, new Timer(runThreadName, true)).
Sage

@Sage không phải lo lắng. Một chuỗi daemon vẫn ổn nếu bạn không thực hiện bất kỳ IO nào. Trường hợp sử dụng mà tôi đã viết này chỉ là một lớp chữa cháy và quên đơn giản để khởi động một số luồng để thực hiện một số nhiệm vụ vệ sinh hàng ngày. Tôi cho rằng nếu bạn đang thực hiện đọc cơ sở dữ liệu trong chuỗi tác vụ hẹn giờ như yêu cầu của OP có thể chỉ ra, thì bạn không nên sử dụng Daemon và sẽ cần một số loại phương thức dừng mà bạn sẽ phải gọi để cho phép ứng dụng của mình kết thúc. stackoverflow.com/questions/7067578/…
PaddyD

@PaddyD Có phải phần cuối cùng tức là phần sử dụng SchedisedExecutorSerive đúng không ??? Cách lớp ẩn danh được tạo ra trông không đúng về cú pháp. Ngoài ra newSingleThreadExecutor () sẽ không có phương thức lịch trình phải không ??
FReeze FRancis

6

Bạn đã xem xét sử dụng một cái gì đó như Quartz Scheduler ? Thư viện này có một cơ chế để lập lịch các tác vụ chạy vào một khoảng thời gian nhất định mỗi ngày bằng cách sử dụng biểu thức cron like (hãy xem CronScheduleBuilder).

Một số mã ví dụ (không được kiểm tra):

public class GetDatabaseJob implements InterruptableJob
{
    public void execute(JobExecutionContext arg0) throws JobExecutionException
    {
        getFromDatabase();
    }
}

public class Example
{
    public static void main(String[] args)
    {
        JobDetails job = JobBuilder.newJob(GetDatabaseJob.class);

        // Schedule to run at 5 AM every day
        ScheduleBuilder scheduleBuilder = 
                CronScheduleBuilder.cronSchedule("0 0 5 * * ?");
        Trigger trigger = TriggerBuilder.newTrigger().
                withSchedule(scheduleBuilder).build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.scheduleJob(job, trigger);

        scheduler.start();
    }
}

Có nhiều công việc hơn một chút trước và bạn có thể cần phải viết lại mã thực thi công việc của mình, nhưng nó sẽ cung cấp cho bạn nhiều quyền kiểm soát hơn đối với cách bạn muốn công việc của mình chạy. Ngoài ra, việc thay đổi lịch trình sẽ dễ dàng hơn nếu bạn cần.


5

Java8:
Phiên bản nâng cấp của tôi từ câu trả lời hàng đầu:

  1. Đã khắc phục tình huống khi Máy chủ ứng dụng web không muốn dừng, do luồng luồng có luồng nhàn rỗi
  2. Không có đệ quy
  3. Chạy tác vụ với giờ địa phương tùy chỉnh của bạn, trong trường hợp của tôi, đó là Belarus, Minsk


/**
 * Execute {@link AppWork} once per day.
 * <p>
 * Created by aalexeenka on 29.12.2016.
 */
public class OncePerDayAppWorkExecutor {

    private static final Logger LOG = AppLoggerFactory.getScheduleLog(OncePerDayAppWorkExecutor.class);

    private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);

    private final String name;
    private final AppWork appWork;

    private final int targetHour;
    private final int targetMin;
    private final int targetSec;

    private volatile boolean isBusy = false;
    private volatile ScheduledFuture<?> scheduledTask = null;

    private AtomicInteger completedTasks = new AtomicInteger(0);

    public OncePerDayAppWorkExecutor(
            String name,
            AppWork appWork,
            int targetHour,
            int targetMin,
            int targetSec
    ) {
        this.name = "Executor [" + name + "]";
        this.appWork = appWork;

        this.targetHour = targetHour;
        this.targetMin = targetMin;
        this.targetSec = targetSec;
    }

    public void start() {
        scheduleNextTask(doTaskWork());
    }

    private Runnable doTaskWork() {
        return () -> {
            LOG.info(name + " [" + completedTasks.get() + "] start: " + minskDateTime());
            try {
                isBusy = true;
                appWork.doWork();
                LOG.info(name + " finish work in " + minskDateTime());
            } catch (Exception ex) {
                LOG.error(name + " throw exception in " + minskDateTime(), ex);
            } finally {
                isBusy = false;
            }
            scheduleNextTask(doTaskWork());
            LOG.info(name + " [" + completedTasks.get() + "] finish: " + minskDateTime());
            LOG.info(name + " completed tasks: " + completedTasks.incrementAndGet());
        };
    }

    private void scheduleNextTask(Runnable task) {
        LOG.info(name + " make schedule in " + minskDateTime());
        long delay = computeNextDelay(targetHour, targetMin, targetSec);
        LOG.info(name + " has delay in " + delay);
        scheduledTask = executorService.schedule(task, delay, TimeUnit.SECONDS);
    }

    private static long computeNextDelay(int targetHour, int targetMin, int targetSec) {
        ZonedDateTime zonedNow = minskDateTime();
        ZonedDateTime zonedNextTarget = zonedNow.withHour(targetHour).withMinute(targetMin).withSecond(targetSec).withNano(0);

        if (zonedNow.compareTo(zonedNextTarget) > 0) {
            zonedNextTarget = zonedNextTarget.plusDays(1);
        }

        Duration duration = Duration.between(zonedNow, zonedNextTarget);
        return duration.getSeconds();
    }

    public static ZonedDateTime minskDateTime() {
        return ZonedDateTime.now(ZoneId.of("Europe/Minsk"));
    }

    public void stop() {
        LOG.info(name + " is stopping.");
        if (scheduledTask != null) {
            scheduledTask.cancel(false);
        }
        executorService.shutdown();
        LOG.info(name + " stopped.");
        try {
            LOG.info(name + " awaitTermination, start: isBusy [ " + isBusy + "]");
            // wait one minute to termination if busy
            if (isBusy) {
                executorService.awaitTermination(1, TimeUnit.MINUTES);
            }
        } catch (InterruptedException ex) {
            LOG.error(name + " awaitTermination exception", ex);
        } finally {
            LOG.info(name + " awaitTermination, finish");
        }
    }

}

1
Tôi có yêu cầu tương tự. Tôi phải lên lịch công việc cho một ngày vào thời điểm nhất định. Sau khi công việc đã lên lịch hoàn thành, hãy lên lịch công việc cho ngày hôm sau vào thời điểm nhất định. Câu hỏi của tôi là làm thế nào để biết được nhiệm vụ đã lên lịch đã hoàn thành hay chưa. Khi tôi biết công việc đã lên lịch đã hoàn thành thì chỉ tôi mới có thể lên lịch cho ngày hôm sau.
amitwdh

2

Tôi đã có một vấn đề tương tự. Tôi đã phải lên lịch cho một loạt các nhiệm vụ sẽ được thực hiện trong một ngày bằng cách sử dụng ScheduledExecutorService. Điều này đã được giải quyết bằng một nhiệm vụ bắt đầu lúc 3:30 sáng, lên lịch cho tất cả các nhiệm vụ khác tương đối với thời gian hiện tại của anh ấy . Và tự lên lịch cho ngày hôm sau lúc 3:30 sáng.

Với kịch bản này, tiết kiệm ánh sáng ban ngày không còn là vấn đề nữa.


2

Bạn có thể sử dụng phân tích cú pháp ngày đơn giản, nếu thời gian trong ngày là trước bây giờ, hãy bắt đầu vào ngày mai:

  String timeToStart = "12:17:30";
  SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss");
  SimpleDateFormat formatOnlyDay = new SimpleDateFormat("yyyy-MM-dd");
  Date now = new Date();
  Date dateToStart = format.parse(formatOnlyDay.format(now) + " at " + timeToStart);
  long diff = dateToStart.getTime() - now.getTime();
  if (diff < 0) {
    // tomorrow
    Date tomorrow = new Date();
    Calendar c = Calendar.getInstance();
    c.setTime(tomorrow);
    c.add(Calendar.DATE, 1);
    tomorrow = c.getTime();
    dateToStart = format.parse(formatOnlyDay.format(tomorrow) + " at " + timeToStart);
    diff = dateToStart.getTime() - now.getTime();
  }

  ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);            
  scheduler.scheduleAtFixedRate(new MyRunnableTask(), TimeUnit.MILLISECONDS.toSeconds(diff) ,
                                  24*60*60, TimeUnit.SECONDS);

1

Chỉ để thêm vào câu trả lời của Victor .

Tôi khuyên bạn nên thêm một séc để xem, nếu biến (trong trường hợp của anh ta là dài midnight) cao hơn 1440. Nếu có, tôi sẽ bỏ qua .plusDays(1), nếu không, nhiệm vụ sẽ chỉ chạy vào ngày mốt.

Tôi đã làm nó đơn giản như thế này:

Long time;

final Long tempTime = LocalDateTime.now().until(LocalDate.now().plusDays(1).atTime(7, 0), ChronoUnit.MINUTES);
if (tempTime > 1440) {
    time = LocalDateTime.now().until(LocalDate.now().atTime(7, 0), ChronoUnit.MINUTES);
} else {
    time = tempTime;
}

Nó đơn giản hóa nếu bạn tận dụngtruncatedTo()
Mark Jeronimus

1

Ví dụ sau phù hợp với tôi

public class DemoScheduler {

    public static void main(String[] args) {

        // Create a calendar instance
        Calendar calendar = Calendar.getInstance();

        // Set time of execution. Here, we have to run every day 4:20 PM; so,
        // setting all parameters.
        calendar.set(Calendar.HOUR, 8);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.AM_PM, Calendar.AM);

        Long currentTime = new Date().getTime();

        // Check if current time is greater than our calendar's time. If So,
        // then change date to one day plus. As the time already pass for
        // execution.
        if (calendar.getTime().getTime() < currentTime) {
            calendar.add(Calendar.DATE, 1);
        }

        // Calendar is scheduled for future; so, it's time is higher than
        // current time.
        long startScheduler = calendar.getTime().getTime() - currentTime;

        // Setting stop scheduler at 4:21 PM. Over here, we are using current
        // calendar's object; so, date and AM_PM is not needed to set
        calendar.set(Calendar.HOUR, 5);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.AM_PM, Calendar.PM);

        // Calculation stop scheduler
        long stopScheduler = calendar.getTime().getTime() - currentTime;

        // Executor is Runnable. The code which you want to run periodically.
        Runnable task = new Runnable() {

            @Override
            public void run() {

                System.out.println("test");
            }
        };

        // Get an instance of scheduler
        final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        // execute scheduler at fixed time.
        scheduler.scheduleAtFixedRate(task, startScheduler, stopScheduler, MILLISECONDS);
    }
}

tham khảo: https://chynten.wordpress.com/2016/06/03/java-scheduler-to-run-every-day-on-specific-time/


1

Bạn có thể sử dụng lớp học dưới đây để lên lịch công việc của mình mỗi ngày vào thời gian cụ thể

package interfaces;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class CronDemo implements Runnable{

    public static void main(String[] args) {

        Long delayTime;

        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        final Long initialDelay = LocalDateTime.now().until(LocalDate.now().plusDays(1).atTime(12, 30), ChronoUnit.MINUTES);

        if (initialDelay > TimeUnit.DAYS.toMinutes(1)) {
            delayTime = LocalDateTime.now().until(LocalDate.now().atTime(12, 30), ChronoUnit.MINUTES);
        } else {
            delayTime = initialDelay;
        }

        scheduler.scheduleAtFixedRate(new CronDemo(), delayTime, TimeUnit.DAYS.toMinutes(1), TimeUnit.MINUTES);

    }

    @Override
    public void run() {
        System.out.println("I am your job executin at:" + new Date());
    }
}

1
Vui lòng không sử dụng lỗi thời DateTimeUnittrong năm 2019
Mark Jeronimus

0

Điều gì sẽ xảy ra nếu máy chủ của bạn gặp sự cố lúc 4:59 sáng và quay lại lúc 5:01 sáng? Tôi nghĩ rằng nó sẽ chỉ bỏ qua cuộc chạy. Tôi muốn giới thiệu công cụ lập lịch liên tục như Quartz, sẽ lưu trữ dữ liệu lịch trình của nó ở đâu đó. Sau đó, nó sẽ thấy rằng lần chạy này vẫn chưa được thực hiện và sẽ thực hiện lúc 5:01 sáng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.