Планирование задач весной

У нас есть требование, когда мы должны собирать документы в течение 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, используют для задачи планирования?

Тогда надо было у них спросить :)

Jai 22.02.2019 07:37

Да, они не звучали убедительно, поэтому я хотел понять плюсы и минусы использования Thread.sleep().

Apurv 22.02.2019 07:39
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
428
2

Ответы 2

Все, что вам нужно сделать здесь, это использовать ScheduledExecutorService, чтобы запланировать поток и обеспечить правильную частоту, как здесь.

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);    

Thread t1= new PushDocumentsToService();    
scheduledThreadPool.scheduleAtFixedRate(t1, 0, 30,TimeUnit.SECONDS);

Вместо этого класс PushDocumentsToService, вероятно, следует изменить, чтобы реализовать Runnable. Потоки уже выполняются исполнителем, поэтому это сбивает с толку.

Jai 22.02.2019 07:47

@Jai согласился. Ваше предложение точное, я думал об этом, но позже пришел к выводу, что существующий дизайн не меняется.

Dark Knight 22.02.2019 08:21

Если у вас есть библиотека Spring Scheduling в вашем пути к классам, добавьте @Scheduled аннотация к методу, который вы хотите выполнять в течение определенного периода времени. Не нужно расширять Thread или реализовывать Runnable; обо всем этом позаботятся от вашего имени через Spring.

Вы знаете, пока приложение Бег.

@Scheduled(cron = "30 * * * * *")
public void loadDataIntoRepository() {
    // your code
}

Для этого больной рекомендуется использовать Thread.sleep по нескольким причинам:

  • Поток, выполняющий ваш код теперь заблокирован в течение периода ожидания. 30 минут — это очень долгий период времени, в течение которого ваша тема будет заблокирована.
  • Ваш поток может быть прерван, и у вас не будет реального способа восстановиться из состояния ошибки.
  • Вы не хотите заново изобретать колесо с планированием, когда эта функциональность уже существует и уже хорошо протестирована для удобства сопровождения.

Просто любопытно, что именно плохого, когда поток блокируется на очень длительный период времени? Кроме того, если экземпляр Thread скрыт внутри (т. е. закрытого поля) класса, то не будет ли проблема с прерыванием иметь значение?

Jai 22.02.2019 08:26

@makoto Я понимаю, что буду изобретать велосипед, но просто из любопытства. Разве Spring Scheduler не использует Thread.sleep внутри или использует какие-то другие нативные методы?

Apurv 22.02.2019 08:57

@Apurv: Вероятно, это делает, но независимо от того, что он использует, это деталь реализации, а не то, о чем нам нужно беспокоиться на этом уровне.

Makoto 22.02.2019 17:14

@Apurv: когда поток заблокирован, это означает, что никакая обработка не может произойти, пока этот поток не разблокируется. Если этот поток удерживает ресурс, никакой другой поток не может использовать этот ресурс, пока он не будет освобожден. Это может привести к тупиковой (или динамической) блокировке, ни одна из которых не является желательной или способствует бесперебойной работе приложения.

Makoto 22.02.2019 17:15

Другие вопросы по теме