Подтвердить что ты не робот

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

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

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


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

После некоторых поисков я нашел несколько таких вопросов, но они действительно не затрагивают то, что я пытаюсь сделать:

Мне не нужно ничего сложного; Я просто хочу сделать что-то через определенное время, оставив всю оставшуюся часть программы.

Как мне следует планировать одноразовую задачу "делать что-то"?

4b9b3361

Ответ 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 Timer vs ExecutorService? по причинам, чтобы избежать использования Timer в пользу ExecutorService.