У нас есть требование, когда мы должны собирать документы в течение X минут в базе данных, где X может быть 30-60. Как только эти документы собраны в базе данных, мы должны отправить их в отдельную службу через вызов REST.
Поскольку эти документы не будут очень большими, мы объединяем их вместе, а затем объединяем.
Теперь эти документы должны быть отправлены через фиксированный интервал, поэтому я подумал о создании отдельного потока, который извлекает записи из базы данных, отправляет их в службу, и как только служба отвечает 200 OK, я удаляю эти записи из базы данных и поток переходит в спящий режим на X минут.
class PushDocumentsToService extends Thread{
DocumentRepository documentRepository;
DocumentProcessingService documentProcessingService
public void run(){
List<Document> list = documentRepository.getAllDocuments();
Integer statusCode = documentProcessingService.sendDocuments(list);
if (statusCode == 200)
documentRepository.remove(list);
try{
Thread.sleep(30*60);
}catch(..){..}
}
}
Теперь несколько моих коллег посоветовали мне не использовать Thread.sleep в моем коде. Я не могу понять пагубных последствий
Thread.sleep()
Также какие методы библиотеки и фреймворки, такие как Spring Scheduler и Google Guava, используют для задачи планирования?
Да, они не звучали убедительно, поэтому я хотел понять плюсы и минусы использования Thread.sleep().




Все, что вам нужно сделать здесь, это использовать ScheduledExecutorService, чтобы запланировать поток и обеспечить правильную частоту, как здесь.
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
Thread t1= new PushDocumentsToService();
scheduledThreadPool.scheduleAtFixedRate(t1, 0, 30,TimeUnit.SECONDS);
Вместо этого класс PushDocumentsToService, вероятно, следует изменить, чтобы реализовать Runnable. Потоки уже выполняются исполнителем, поэтому это сбивает с толку.
@Jai согласился. Ваше предложение точное, я думал об этом, но позже пришел к выводу, что существующий дизайн не меняется.
Если у вас есть библиотека Spring Scheduling в вашем пути к классам, добавьте @Scheduled аннотация к методу, который вы хотите выполнять в течение определенного периода времени. Не нужно расширять Thread или реализовывать Runnable; обо всем этом позаботятся от вашего имени через Spring.
Вы знаете, пока приложение Бег.
@Scheduled(cron = "30 * * * * *")
public void loadDataIntoRepository() {
// your code
}
Для этого больной рекомендуется использовать Thread.sleep по нескольким причинам:
Просто любопытно, что именно плохого, когда поток блокируется на очень длительный период времени? Кроме того, если экземпляр Thread скрыт внутри (т. е. закрытого поля) класса, то не будет ли проблема с прерыванием иметь значение?
@makoto Я понимаю, что буду изобретать велосипед, но просто из любопытства. Разве Spring Scheduler не использует Thread.sleep внутри или использует какие-то другие нативные методы?
@Apurv: Вероятно, это делает, но независимо от того, что он использует, это деталь реализации, а не то, о чем нам нужно беспокоиться на этом уровне.
@Apurv: когда поток заблокирован, это означает, что никакая обработка не может произойти, пока этот поток не разблокируется. Если этот поток удерживает ресурс, никакой другой поток не может использовать этот ресурс, пока он не будет освобожден. Это может привести к тупиковой (или динамической) блокировке, ни одна из которых не является желательной или способствует бесперебойной работе приложения.
Тогда надо было у них спросить :)