Цикл Java каждую минуту

Я хочу написать цикл на Java, который сначала запускается и выглядит следующим образом:

while (!x){
    //wait one minute or two

    //execute code
}

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


person Robert Cardona    schedule 24.04.2010    source источник


Ответы (5)


Используйте Thread.sleep(long millis).

Заставляет выполняющийся в данный момент поток переходить в спящий режим (временно прекращать выполнение) на указанное количество миллисекунд в зависимости от точности системных таймеров и планировщиков. Поток не теряет право собственности на какие-либо мониторы.

Одна минута будет (60*1000) = 60000 миллисекунды.


Например, этот цикл будет печатать текущее время каждые 5 секунд:

    try {
        while (true) {
            System.out.println(new Date());
            Thread.sleep(5 * 1000);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

Если ваш период сна становится слишком большим для int, явно вычислите в long (например, 1000L).

person polygenelubricants    schedule 24.04.2010
comment
Я попробовал, и это не сработало, мой код выглядит следующим образом: if (link.equalsIgnoreCase(exit) && count › 0) { boolean fetched = false; интервал myCounter = 0; try { while (!fetched) { System.out.println(Проверка ( + myCounter + )); если (session.areLinkDoneFetching()) { session.getFetchData(); сессия.clearList(); получено = верно; } мойСчетчик++; Thread.sleep(5 * 1000); } } catch (InterruptedException e) { e.printStackTrace(); } } - person Robert Cardona; 24.04.2010
comment
Что значит не получилось? Не компилируется? Он не спит по 5 секунд за раз? - person polygenelubricants; 24.04.2010
comment
он запускается один раз, а затем ничего не делает. но программа все еще работает. - person Robert Cardona; 24.04.2010
comment
что-то не так с моим кодом, извините, он хорошо работает сам по себе. хотя спасибо, это было именно то, что я искал - person Robert Cardona; 24.04.2010
comment
Лично я предпочитаю пользователя решения класса Timer ниже. - person Alan Thomas; 23.07.2016
comment
Пакет java.util.concurrent, встроенный в Java 5 и более поздние версии, является заменой кода, показанного в этом ответе, а также заменой класса Timer. См. интерфейс ScheduledExecutorService. - person Basil Bourque; 27.12.2016

Вы можете использовать таймер.

Timer timer = new Timer();

timer.schedule( new TimerTask() {
    public void run() {
       // do your work 
    }
 }, 0, 60*1000);

Когда придет время

  timer.cancel();

Чтобы закрыть его.

person OscarRyz    schedule 24.04.2010
comment
Если для запуска TimerTask требуется, скажем, 55 секунд, будет ли он ждать всего 5 секунд перед каждым запуском или действительно будет ждать минуту, как спросил OP? - person polygenelubricants; 24.04.2010
comment
@poly: подождет минуту, как и просил ОП. Timer#scheduleAtFixedRate() делает то, что вы говорите. - person BalusC; 24.04.2010
comment
@BalusC: А, интересно! schedule запускается с фиксированной задержкой между выполнениями, а scheduleAtFixedRate запускается с фиксированным интервалом. Ницца! - person polygenelubricants; 24.04.2010
comment
Я попробовал это и поместил свой код в метод запуска, но получил ошибку о доступе к локальным переменным из внутреннего класса. - person Robert Cardona; 24.04.2010
comment
@Robert: В этом случае попробуйте сделать эти переменные final. - person Platinum Azure; 02.05.2012
comment
Что, если мы запрограммируем таймер с фиксированной частотой для выполнения задачи каждую минуту, но сама задача выполняется за 1,5 минуты (выполнения перекрываются)? Будут ли выполняться обе задачи параллельно? Что было бы простым способом гарантировать, что все, к чему обращается метод run(), подготовлено для параллелизма? - person beam022; 02.06.2020

ScheduledExecutorService

Ответ Ли близок, но запускается только один раз. Вопрос, кажется, просит работать бесконечно, пока не изменится внешнее состояние (пока не изменится ответ от веб-сайта/службы).

Интерфейс ScheduledExecutorService является частью пакета java.util.concurrent, встроенного в Java 5 и более поздних версий, в качестве более современной замены старого Timer.

Вот полный пример. Вызовите либо scheduleAtFixedRate или scheduleWithFixedDelay.

ScheduledExecutorService executor = Executors.newScheduledThreadPool ( 1 );

Runnable r = new Runnable () {
    @Override
    public void run () {
        try {  // Always wrap your Runnable with a try-catch as any uncaught Exception causes the ScheduledExecutorService to silently terminate.
            System.out.println ( "Now: " + Instant.now () );  // Our task at hand in this example: Capturing the current moment in UTC.
            if ( Boolean.FALSE ) {  // Add your Boolean test here to see if the external task is fonud to be completed, as described in this Question.
                executor.shutdown ();  // 'shutdown' politely asks ScheduledExecutorService to terminate after previously submitted tasks are executed.
            }

        } catch ( Exception e ) {
            System.out.println ( "Oops, uncaught Exception surfaced at Runnable in ScheduledExecutorService." );
        }
    }
};

try {
    executor.scheduleAtFixedRate ( r , 0L , 5L , TimeUnit.SECONDS ); // ( runnable , initialDelay , period , TimeUnit )
    Thread.sleep ( TimeUnit.MINUTES.toMillis ( 1L ) ); // Let things run a minute to witness the background thread working.
} catch ( InterruptedException ex ) {
    Logger.getLogger ( App.class.getName () ).log ( Level.SEVERE , null , ex );
} finally {
    System.out.println ( "ScheduledExecutorService expiring. Politely asking ScheduledExecutorService to terminate after previously submitted tasks are executed." );
    executor.shutdown ();
}

Ожидайте вывод следующим образом:

Now: 2016-12-27T02:52:14.951Z
Now: 2016-12-27T02:52:19.955Z
Now: 2016-12-27T02:52:24.951Z
Now: 2016-12-27T02:52:29.951Z
Now: 2016-12-27T02:52:34.953Z
Now: 2016-12-27T02:52:39.952Z
Now: 2016-12-27T02:52:44.951Z
Now: 2016-12-27T02:52:49.953Z
Now: 2016-12-27T02:52:54.953Z
Now: 2016-12-27T02:52:59.951Z
Now: 2016-12-27T02:53:04.952Z
Now: 2016-12-27T02:53:09.951Z
ScheduledExecutorService expiring. Politely asking ScheduledExecutorService to terminate after previously submitted tasks are executed.
Now: 2016-12-27T02:53:14.951Z
person Basil Bourque    schedule 27.12.2016

Если вы используете приложение SpringBoot, это так же просто, как

Запланированный процесс

@Log
@Component
public class ScheduledProcess {

    @Scheduled(fixedRate = 5000)
    public void run() {
        log.info("this runs every 5 seconds..");
    }

}

Приложение.класс

@SpringBootApplication
// ADD THIS ANNOTATION TO YOUR APPLICATION CLASS
@EnableScheduling
public class SchedulingTasksApplication {

    public static void main(String[] args) {
        SpringApplication.run(SchedulingTasksApplication.class);
    }
}
person Eduardo Dennis    schedule 27.02.2021

person    schedule
comment
Не забудьте shutdown() после использования, иначе поток зависнет. О, ОП не просил планировать по фиксированной ставке. Просто используйте расписание(). - person BalusC; 24.04.2010
comment
обратите внимание, что он не остановит поток, если он находится в цикле. shutdownNow также прервет поток (который вам нужно обработать) - person user2130951; 31.08.2016
comment
вы можете использовать Executors.newSingleThreadScheduledExecutor() вместо Executors.newScheduledThreadPool(1);, если вам нужен только один поток - person Nicofisi; 28.09.2017