【问题标题】:Schedule monthly task using ScheduledExecutorService使用 ScheduledExecutorService 安排每月任务
【发布时间】:2016-12-25 14:27:52
【问题描述】:

我想在每月的特定日期的特定时间安排一项任务。每次运行之间的间隔可以设置在 1 到 12 个月之间。在 java 中,可以使用 ScheduledExecutorService 以固定的时间间隔安排任务。由于一个月的天数不固定,如何实现?

提前致谢。

【问题讨论】:

    标签: java scheduled-tasks


    【解决方案1】:

    如果您在 Java EE 环境中运行,则应使用 TimerService@Schedule 注释。但由于您讨论的是 ScheduledExecutorService,它不允许在 Java EE 容器中使用,我假设您没有在其中运行。

    使用 ScheduledExecutorService 时,您可以让任务自己安排下一次迭代:

    final ScheduledExecutorService executor = /* ... */ ;
    
    Runnable task = new Runnable() {
        @Override
        public void run() {
            ZonedDateTime now = ZonedDateTime.now();
            long delay = now.until(now.plusMonths(1), ChronoUnit.MILLIS);
    
            try {
                // ...
            } finally {
                executor.schedule(this, delay, TimeUnit.MILLISECONDS);
            }
        }
    };
    
    int dayOfMonth = 5;
    
    ZonedDateTime dateTime = ZonedDateTime.now();
    if (dateTime.getDayOfMonth() >= dayOfMonth) {
        dateTime = dateTime.plusMonths(1);
    }
    dateTime = dateTime.withDayOfMonth(dayOfMonth);
    executor.schedule(task,
        ZonedDateTime.now().until(dateTime, ChronoUnit.MILLIS),
        TimeUnit.MILLISECONDS);
    

    在 Java 8 之前的版本中,您可以使用日历来做同样的事情:

    final ScheduledExecutorService executor = /* ... */ ;
    
    Runnable task = new Runnable() {
        @Override
        public void run() {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MONTH, 1);
            long delay =
                calendar.getTimeInMillis() - System.currentTimeMillis();
    
            try {
                // ...
            } finally {
                executor.schedule(this, delay, TimeUnit.MILLISECONDS);
            }
        }
    };
    
    int dayOfMonth = 5;
    
    Calendar calendar = Calendar.getInstance();
    if (calendar.get(Calendar.DAY_OF_MONTH) >= dayOfMonth) {
        calendar.add(Calendar.MONTH, 1);
    }
    calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
    executor.schedule(task,
        calendar.getTimeInMillis() - System.currentTimeMillis(),
        TimeUnit.MILLISECONDS);
    

    【讨论】:

      【解决方案2】:

      既然你想要一个在很长一段时间内执行一次的东西,你就需要一些可靠的东西。

      看看石英:

      http://www.quartz-scheduler.org/documentation/quartz-2.x/cookbook/MonthlyTrigger.html

      【讨论】:

        【解决方案3】:

        在带有@Schedule 注释的JavaEE 中使用Last 关键字。 示例:

        @Schedule(second = "59", minute = "59", hour = "23", dayOfMonth = "Last", persistent = false)
        

        【讨论】:

          猜你喜欢
          • 2010-10-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-22
          • 2016-09-30
          • 2011-11-09
          • 1970-01-01
          相关资源
          最近更新 更多