如何将任务安排到 运行 一次?

How do I schedule a task to run once?

我想延迟做某事,比如设置一个倒数计时器,在一定时间后 "do a thing"。

我希望程序的其余部分在我等待时保持 运行ning,因此我尝试制作自己的 Thread,其中包含一分钟的延迟:

public class Scratch {
    private static boolean outOfTime = false;

    public static void main(String[] args) {
        Thread countdown = new Thread() {
            @Override
            public void run() {
                try {
                    // wait a while
                    System.out.println("Starting one-minute countdown now...");
                    Thread.sleep(60 * 1000);

                    // do the thing
                    outOfTime = true;
                    System.out.println("Out of time!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        countdown.start();

        while (!outOfTime) {
            try {
                Thread.sleep(1000);
                System.out.println("do other stuff here");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


虽然这或多或少奏效了,但似乎应该有更好的方法来做到这一点。

经过一番搜索,我发现了一堆类似这样的问题,但它们并没有真正解决我想要做的事情:

我不需要这么复杂的东西;我只想在一定时间后做一件事情,同时让程序的其余部分仍然 运行.

我应该如何将一次性任务安排给 "do a thing"?

虽然 java.util.Timer 曾经是安排未来任务的好方法,但现在更可取的是 1 而不是在 java.util.concurrent包.

有一个ScheduledExecutorService专门用于运行延迟后的命令(或定期执行它们,但这与此问题无关)。

它有一个schedule(Runnable, long, TimeUnit)方法

Creates and executes a one-shot action that becomes enabled after the given delay.


使用 ScheduledExecutorService 你可以像这样重写你的程序:

import java.util.concurrent.*;

public class Scratch {
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    public static void main(String[] args) {
        System.out.println("Starting one-minute countdown now...");
        ScheduledFuture<?> countdown = scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                // do the thing
                System.out.println("Out of time!");
            }}, 1, TimeUnit.MINUTES);

        while (!countdown.isDone()) {
            try {
                Thread.sleep(1000);
                System.out.println("do other stuff here");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        scheduler.shutdown();
    }
}

您通过这种方式获得的好处之一是您从调用 schedule().

中返回的 ScheduledFuture<?> 对象

这样可以去掉多余的boolean变量,直接检查作业是否有运行.

如果您不想再等待,您也可以通过调用其cancel()方法取消计划任务。


1请参阅 Java Timer vs ExecutorService? 了解避免使用 Timer 而使用 ExecutorService 的原因。

谢谢它对我有用。我使用调度程序以运行时计算的批处理间隔来安排任务。

    manualTriggerBatchJob.setSchedulingProperties(pblId, batchInterval);
    ScheduledExecutorService scheduledExecutorService =
            Executors.newScheduledThreadPool(5);
    @SuppressWarnings("unchecked")
    ScheduledFuture scheduledFuture =
            scheduledExecutorService.schedule(manualTriggerBatchJob,
            batchIntervalInMin,TimeUnit.MILLISECONDS);