Пробуждение потока, созданного с помощью ScheduledExecutorService

#java #multithreading #scheduledexecutorservice

#java #многопоточность #scheduledexecutorservice

Вопрос:

Я использую ScheduledExecutorService для создания потока, как показано ниже:

     private ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
    private ScheduledFuture<?> scheduledFuture = ses.scheduleWithFixedDelay(() -> { cleanup(); }, 0L, 5L, TimeUnit.SECONDS);
 

Между выполнением функции очистки происходит спящий режим продолжительностью 5 секунд.

При определенных условиях существует ли условие для пробуждения этого потока для запуска очистки вместо ожидания 5 секунд для ее запуска?

Пример: во время T1 -> вызывается очистка, в T1 2s -> я хочу разбудить поток, чтобы выполнить явную очистку

Комментарии:

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

2. Ну, мне нужно выполнять очистку каждые 5 секунд. Но между ними может возникнуть необходимость запустить очистку, скажем, между 10-й и 15-й секундами, каков способ явного пробуждения потока?

Ответ №1:

я хочу разбудить поток, чтобы выполнить явную очистку.

Почему бы просто не вызвать cleanup() любой другой поток, который сочтет нужным?

 void someTerriblyImportantFunction(...) {
    ...
    if (thisPlaceNeedsToBeCleanedUp_Like_NOW()) {
        cleanup();
    }
    ...
}
 

Я могу это сделать, но я хотел, чтобы поток всегда выполнял очистку.

Прежде всего, вы не можете зависеть от пула потоков, чтобы всегда использовать один и тот же поток при выполнении вашей задачи очистки. Вы создали пул путем вызова Executors.newScheduledThreadPool(1) , но 1 аргумент указывает только минимальное количество потоков в пуле. В программе, которая использует один и тот же пул потоков для более чем одной вещи, пул может свободно создавать и уничтожать рабочие потоки по мере необходимости, если он всегда держит один поток готовым.

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


PS, Также обратите внимание на то, что @Hulk сказал в комментарии: если cleanup() требуется больше времени, чем вызывающий абонент готов ждать, тогда другим вариантом будет отправка задачи «one-shot», которая должна быть запланирована как можно скорее тем же пулом потоков.

 void someTerriblyImportantFunction(...) {
    ...
    if (thisPlaceNeedsToBeCleanedUp_RealSoon()) {
        ses.schedule(() -> { cleanup(); }, 1L, TimeUnit.MICROSECONDS);
    }
    ...
}
 

Комментарии:

1. Я могу это сделать, но я хотел, чтобы поток всегда выполнял очистку.