Метод Sync Scheduled запускает асинхронный метод — Spring @Scheduled, @Async

Я использую аннотацию @Scheduled и @Async для Spring.

Моя цель

Чтобы запланировать метод синхронизации, который запускает цикл for, а этот цикл запускает асинхронный метод, поэтому следующему значению в цикле не нужно ждать завершения метода.

Посмотрите мой код ниже:

/**
 *  Explanation: Scheduling async task for getting new hired candidates from the Lumesse Queue and saving the received data.
 */
@LoggableDebug
@Scheduled(fixedRateString = "${scheduler.insertCandidateFromQueueInDB.fixedRate}")
public void insertNewHiredCandidateFromQueueInDbScheduler() {
    for(EnvironmentContext environmentContext: context) {
        if(environmentContext.isActive()) {
            environmentAsyncHandlerInsertNewHiredCandidateFromQueueInDb(environmentContext);
        }
    }
}

/**
 * @param environmentContext
 * Explanation: Async task for getting new hired candidates from the Lumesse Queue and saving the received data.
 */
@LoggableDebug
@Async
public void environmentAsyncHandlerInsertNewHiredCandidateFromQueueInDb(EnvironmentContext environmentContext) {
    CandidateLumesse candidateLumesse;
    candidateLumesse = lumesseConnectorService.getNewHiredCandidateDataFromQueue(environmentContext);   
}

Проблема:

Мой асинхронный метод не работает с разными задачами. Это работает только тогда, когда я помещаю аннотацию @Async также в свой запланированный метод. Но тогда мой запланированный метод будет работать асинхронно, а это не то, чего я хочу. Запланированный метод должен выполняться синхронно, но вызываемый метод в цикле for должен выполняться асинхронно.

Попытки

Я пробовал обходной путь, подобный этому:

Вызов метода Spring @Async внутри метода @Scheduled

-> помещая мои асинхронные методы в другой класс. Так:

@LoggableDebug
@Scheduled(fixedRateString = "${scheduler.insertCandidateFromQueueInDB.fixedRate}")
public void insertNewHiredCandidateFromQueueInDbScheduler() {
    for(EnvironmentContext environmentContext: context) {
        if(environmentContext.isActive()) {
            asyncServiceExecutor.environmentAsyncHandlerInsertNewHiredCandidateFromQueueInDb(environmentContext);
        }
    }
}

проблема в том, что моя запланированная задача выполняется дважды...

Обновить

Я сделал еще несколько журналов, и мой объект создается только один раз:

2018-02-06 13:17:19.053  WARN 13144 --- [           main] 
c.d.l.c.s.LumesseConnectorScheduler      : #### SCHEDULER CLASS CONSTRUCTOR

Моя fixedRate 3000 -> 3 секунды. Кто-то запросил «увеличить его до 30 секунд, чтобы увидеть поток», но все же он выполняется дважды: поэтому через 3 или 30 секунд или независимо от того, на что была установлена ​​фиксированная скорость, он выполнит его дважды вместо одного раза..

2018-02-06 13:17:26.388  WARN 13144 --- [pool-7-thread-1] 
c.d.l.c.s.LumesseConnectorScheduler      : #### START SCHEDULING
2018-02-06 13:17:26.397  WARN 13144 --- [pool-7-thread-1] 
c.d.l.c.s.LumesseConnectorScheduler      : #### START SCHEDULING

-> Время между двумя выполнениями составляет всего несколько очень малых миллисекунд. Я просто не понимаю..

Есть предположения ?


person Tom    schedule 06.02.2018    source источник
comment
какова частота scheduler.insertCandidateFromQueueInDB.fixedRate?   -  person spandey    schedule 06.02.2018
comment
fixedRate: 3000 -> поэтому 3 секунды   -  person Tom    schedule 06.02.2018
comment
увеличьте его до 30 секунд, чтобы увидеть поток   -  person spandey    schedule 06.02.2018
comment
Мой пост обновлен результатами - он ничего не решил   -  person Tom    schedule 06.02.2018
comment
@Tom Это было выполнено дважды, но почему период не 3 или 30 секунд? Судя по отметке времени журнала, интервал очень мал.   -  person xingbin    schedule 06.02.2018
comment
Вот что я имею в виду под казненным дважды. Каждые 3 или 30 секунд он будет выполнять его дважды, а не один раз.   -  person Tom    schedule 06.02.2018
comment
@ Том, я думаю, что нашел причину. Опубликуйте аннотацию, которую вы поместили в класс планировщика.. Позвольте мне проверить это..   -  person xingbin    schedule 06.02.2018
comment
Если он выполняется дважды, вы запускаете его дважды. Возможно, у вас есть сканирование компонентов в вашем контексте как для ContextLoaderListener, так и для DispatcherServlet. Сканирование и настройка одних и тех же компонентов и, таким образом, загрузка приложения дважды, что приводит к двойному планированию.   -  person M. Deinum    schedule 06.02.2018
comment
@ConfigurationProperties(prefix=environment) @Component public class LumesseConnectorScheduler .. Я пробовал Component, Service, Controller, ..   -  person Tom    schedule 06.02.2018
comment
@ M.Deinum Я не использую DispatcherServlet   -  person Tom    schedule 06.02.2018
comment
Несмотря на это, это признак того, что вещи загружаются дважды и, следовательно, выполняются дважды. На самом деле это новый вопрос (на ваш исходный вопрос был дан ответ).   -  person M. Deinum    schedule 06.02.2018
comment
Но когда я удаляю асинхронную аннотацию - задача планирования правильно запускается один раз..   -  person Tom    schedule 06.02.2018
comment
@Tom Попробуйте удалить @ConfigurationProperties(prefix="environment") или @Component   -  person xingbin    schedule 06.02.2018
comment
Если я удалю @Component, он ничего не запустит. Я попытаюсь удалить параметры конфигурации, если это возможно.   -  person Tom    schedule 06.02.2018
comment
Хорошо, я сделал еще несколько журналов: мой объект создается только один раз - так что @M.Deinum это не так, как вы думаете ... но он дважды входит в мой метод планировщика ... :(   -  person Tom    schedule 06.02.2018
comment
Поверьте мне, это так. Если это запланировано дважды, вещи обрабатываются дважды. Это может быть связано с тем, что у вас есть несколько планировщиков, которые обрабатывают вещи, или у вашего компонента есть несколько экземпляров.   -  person M. Deinum    schedule 06.02.2018
comment
Это единственный планировщик в моем приложении, и это единственная работающая задача при запуске моего приложения. Я отредактировал свой пост с результатом журнала, и кажется, что объект создается только один раз.. хм   -  person Tom    schedule 06.02.2018
comment
@ M.Deinum Я считаю, что вы правы, но я не вижу, где это происходит.   -  person Tom    schedule 06.02.2018
comment
@ Том, какая у тебя весенняя версия?   -  person xingbin    schedule 06.02.2018
comment
springBootVersion = '1.5.3.RELEASE'   -  person Tom    schedule 06.02.2018
comment
@ user27149 Я удалил ConfigurationProperties и заменил его новым объектом Autowired. Это работает сейчас! Я опубликую свое решение ниже. Хорошая работа!   -  person Tom    schedule 07.02.2018


Ответы (1)


-> Async работает с моими «Попытками»:

Попытки

Я пробовал обходной путь, подобный этому:

Вызов метода Spring @Async внутри метода @Scheduled

, но у меня возникла новая проблема с двойным выполнением планировщика:

Решение

@user27149 user27149 Попробуйте удалить @ConfigurationProperties(prefix="environment") или @Component

Так что я изменил

@Component
@ConfigurationProperties(prefix="environment")
public class LumesseConnectorScheduler {

    private List<EnvironmentContextImpl> context;

To:

@Component
public class LumesseConnectorScheduler {

    @Autowired
    EnvironmentContextList environmentContextList;

Спасибо за ответы!

person Tom    schedule 07.02.2018