Как запланировать выполнение задачи один раз?

Я хочу отложить что-то делать, по линии установки таймера обратного отсчета, который будет "делать что-то" через определенное количество времени.

Я хочу, чтобы остальная часть моей программы продолжала работать, пока я жду, поэтому я попытался сделать свой собственный 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();
            }
        }
    }
}


Хотя это сработало, более или менее, казалось, что должен быть лучший способ сделать это.

после некоторого поиска я нашел кучу вопросов, подобных этим но на самом деле они не касаются того, что я пытаюсь сделать:

мне ничего не нужно это сложно; я просто хочу сделать одну вещь через определенное количество времени, позволяя остальной части программы все еще работать.

Как я должен планировать одноразовую задачу ,чтобы"сделать что-то"?

1 ответов


С java.util.Timer раньше это был хороший способ планировать будущие задачи, теперь это предпочтительнее1 использовать классы java.util.concurrent пакета.

есть ScheduledExecutorService который предназначен специально для запуска команды после задержки (или для их периодического выполнения, но это не относится к этому вопросу).

у него есть schedule(Runnable, long, TimeUnit) метод

создает и выполняет одноразовое действие, которое включается после заданной задержки.


С помощью 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();
    }
}

одна из приятных вещей, которые вы получаете, делая вещи таким образом, является ScheduledFuture<?> объект, который вы получаете обратно от вызова schedule().

это позволяет избавиться от лишних boolean переменная, и просто проверьте непосредственно, выполняется ли задание.

вы также можете отменить запланированную задачу если вы не хотите больше ждать, назвав его cancel() метод.


1посмотреть таймер Java против ExecutorService? по причинам, чтобы избежать использования Timer в пользу ExecutorService.