将日期格式添加到 ActionListener 的 ScheduledExecutorService

ScheduledExecutorService with dating format added to ActionListener

我了解到在 Java 中,可以使用 ScheduledExecutorService 在一定延迟后执行特定任务。 post 显示如何在特定日期执行任务,但不使用 SimpleDateFormat 。例如,我的格式初始化如下:

dateFormatter = new SimpleDateFormat("MM-dd-yyyy hh:mm aa");

此外,我想执行在 ActionListener 中的 else if 语句下声明的特定任务,如下所示:

foo.addActionListener(e -> {
            if (condition) {

            // some task

            } else if (some other condition) { // what I want to be executed at particular date

            // some other task

            } else {

            // another task

            }
        });

如何在特定日期使用 else if 语句初始化在 and/or 内执行的 ScheduledExecutorService,最好使用 SimpleDateFormat

java.time

请使用 java.time,现代 Java 日期和时间 API 作为您的日期和时间工作。现代的 class 代替旧的 SimpleDateFormatDateTimeFormatter.

static DateTimeFormatter formatter
        = DateTimeFormatter.ofPattern("MM-dd-yyyy hh:mm a", Locale.ENGLISH);

编辑:正如 Basil Bourque 在评论中所说,还要在某个地方声明您的执行程序服务,您可以在不再需要它时将其关闭。例如:

static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);

现在在您的动作侦听器(或您可能喜欢的任何其他地方)中,您可以:

        } else {
            String timeString = "04-01-2020 08:00 AM";
            ZoneId zone = ZoneId.of("America/Curacao");
            ZonedDateTime timeToExecute = LocalDateTime.parse(timeString, formatter)
                    .atZone(zone);
            long delaySeconds = ChronoUnit.SECONDS.between(
                    ZonedDateTime.now(zone), timeToExecute);
            executor.schedule(() -> System.out.println("It’s now " + timeString),
                            delaySeconds, TimeUnit.SECONDS);
        }

记得调用

关闭executor释放资源
    executor.shutdown();

或者,如果您想取消已经安排好的任务,请改用 shutdownNow()

我已经为所需的时间和时区设置了非常随机的值,因此请插入您的值。如果您想要 JVM 的时区设置,ZoneId.systemDefault() 是一个选项。

除许多其他优点外,java.time 更好地支持计算从现在到所需预定时间的时间间隔长度。如果您需要比秒更准确的精度,请改用毫秒、微秒甚至纳秒,其方式非常相似(因为您的字符串似乎只有分钟精度,所以我认为没有必要)。

您提到的 SimpleDateFormat 是臭名昭著的 class 麻烦制造者,您永远不会喜欢使用它。幸运的是它也早就过时了。

Link

Oracle tutorial: Date Time 解释如何使用 java.time.

早点建立执行器服务

How could I initialize a ScheduledExecutorService that is executed within and/or with an else if

你不知道。

不要在需要时初始化执行程序服务。

您可以在其他地方更早地实例化您的 scheduled executor service,并在命名变量中保留引用。稍后根据需要调用该执行程序服务对象。

可以调用该执行程序服务来 运行 应用程序其他部分中的其他类型的任务。执行者服务不需要绑定到单一类型的任务。

重要您必须保留对该执行程序服务的引用,以便它的后备线程池可以在某个时候正常关闭。否则,线程池可能会在其原始应用程序结束后继续 运行ning

一般来说,我建议采用这种方法。

  • 应用程序启动时,建立您的执行程序服务。保留一个参考,以便稍后通过您选择的全局变量进行访问。也许 Singleton, or a Service Locator, or dependency injection such as passing to a constructor.
  • 在您的 应用的 运行 期间,找到现有的执行程序服务。提交您的任务 运行.
  • 应用程序结束时,找到现有的执行程序服务。调用其关闭方法结束其后台线程池。

搜索堆栈溢出。这个话题已经被讨论过很多次了。您将找到示例代码和进一步的讨论。

示例代码

使用 Executors 实用程序 class 实例化执行程序服务。

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ; 

ses 引用存储在您应用的某处。

计算等待时间,如

所示
foo.addActionListener(
    e -> {
        if (condition) {

            doSomethingNow() ;

        } else if (some other condition) { 

            long delaySeconds = … ;  // See: 
            ScheduledExecutorService scheduledExecutorService = Objects.requireNonNull​( … ) ;  // Locate the existing scheduled executor service.
            Runnable task = () -> { System.out.println( "Doing something later. " + Instant.now() ) ; };
            scheduledExecutorService.schedule(
                task ,
                delaySeconds ,
                TimeUnit.SECONDS
            );

        } else {

            doSomethingElseNow() ;

        }
    }
);

当您的应用程序退出时,关闭计划的执行程序服务。

// In the hook for app shut-down.
ScheduledExecutorService scheduledExecutorService = Objects.requireNonNull​( … ) ;  // Locate the existing scheduled executor service.
scheduledExecutorService.shutdown() ;