#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. Я могу это сделать, но я хотел, чтобы поток всегда выполнял очистку.