запланированная задача весенней загрузки зависает

Некоторое время я использовал весеннюю загрузку с @Scheduled, но недавно я обнаружил, что существует опасная скрытая угроза, как описано ниже: я обнаружил, что при запуске приложения и выполнения запланированной задачи несколько раз остается много потоков, ожидающих, но не завершенных, что показано в трассировке стека потока как «kill -3». Чтобы очистить все, что может привести к этой проблеме, я делаю пустую задачу:

    @Component
public class TestJob
{
    /**
     * LOGGER
     */
    private static Logger log = LogManager.getLogger(TestJob.class);

    @Scheduled(fixedDelay = 60000, initialDelay = 1000)
    public void test()
    {
        log.info("---------------[{}]", Thread.currentThread().getId());
    }
}

а это мой журнал:

20151102 11: 54: 50.660 | ИНФОРМАЦИЯ | бассейн-3-поток-2 | --------------- [26] | TestJob.test (TestJob.java:19) 20151102 11: 55: 50.662 | ИНФОРМАЦИЯ | бассейн-3-поток-4 | --------------- [28] | TestJob.test (TestJob.java:19) 20151102 11: 56: 50.664 | ИНФОРМАЦИЯ | бассейн-3-поток-5 | --------------- [33] | TestJob.test (TestJob.java:19) 20151102 11: 57: 50.666 | ИНФОРМАЦИЯ | бассейн-3-поток-6 | --------------- [37] | TestJob.test (TestJob.java:19)

поток стека:

"pool-3-thread-2" # 26 prio = 5 os_prio = 0 tid = 0x00007fbea0cd9800 nid = 0x74f2 ожидание при условии [0x00007fbf0d3d2000] java.lang.Thread.State: WAITING (парковка) на sun.misc.Unsafe.park ( Собственный метод) - парковка для ожидания ‹0x0000000763ed3710> (объект java.util.concurrent.locks.AbstractQueuedSynchronizer $ ConditionObject) в java.util.concurrent.locks.LockSupport.park (LockSupport.java:175) в java.rentutil. .locks.AbstractQueuedSynchronizer $ ConditionObject.await (AbstractQueuedSynchronizer.java:2039) в java.util.concurrent.ScheduledThreadPoolExecutor $ DelayedWorkQueue.take (ScheduledThreadPoolExecutor.java:1088.consreadoolExecutor.java:1088. : 809) на java.util.concurrent.ThreadPoolExecutor.getTask (ThreadPoolExecutor.java:1067) на java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1127) на java.util. current.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:617) в java.lang.Thread.run (Thread.java:745)

"pool-3-thread-4" # 28 prio = 5 os_prio = 0 tid = 0x00007fbea0783800 nid = 0x74f4 ожидание при условии [0x00007fbf0d1d0000] java.lang.Thread.State: WAITING (парковка) в sun.misc.Unsafe.park ( Собственный метод) - парковка для ожидания ‹0x0000000763ed3710> (объект java.util.concurrent.locks.AbstractQueuedSynchronizer $ ConditionObject) в java.util.concurrent.locks.LockSupport.park (LockSupport.java:175) в java.rentutil. .locks.AbstractQueuedSynchronizer $ ConditionObject.await (AbstractQueuedSynchronizer.java:2039) в java.util.concurrent.ScheduledThreadPoolExecutor $ DelayedWorkQueue.take (ScheduledThreadPoolExecutor.java:1088.consreadoolExecutor.java:1088. : 809) на java.util.concurrent.ThreadPoolExecutor.getTask (ThreadPoolExecutor.java:1067) на java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1127) на java.util. current.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:617) в java.lang.Thread.run (Thread.java:745)

Запланированный javadoc говорит

Обработка аннотаций @Scheduled выполняется путем регистрации ScheduledAnnotationBeanPostProcessor.

Я сам не назвал этот класс, только с аннотированным основным классом @EnableScheduling.

Кто-нибудь знает, как исправить эту проблему?

ОБНОВЛЕНИЕ:  Я прикрепил изображение захвата экрана отладки Eclipse, пул увеличивается, и все старые потоки выполняются ... надеюсь, это поможет прояснить мой вопрос.

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

ОБНОВЛЕНИЕ: я думаю, что на этот раз я все понял. размер пула весеннего планировщика загрузки по умолчанию равен 100, и все потоки находятся в рабочем состоянии. Я не понимаю, на чем работает? Я думаю, надо чего-нибудь подождать, почему бы и нет? Кто-нибудь знает, как настроить размер запланированного пула весенней загрузки с аннотацией? Я не использую xml в своем приложении и не хочу вводить его только для планировщика.


person Simon    schedule 02.11.2015    source источник
comment
Помогло бы увеличение размера пула?   -  person Sanjay    schedule 02.11.2015


Ответы (1)


Я вижу в вашем примере абсолютно нормальное поведение. У вас есть запланированная задача, она выполняется каждую минуту другим потоком в пуле потоков. Потоки в пуле потоков находятся в состоянии WAITING (парковка), которое ожидается для пула потоков. Если вы хотите уменьшить количество потоков, вы можете настроить это: http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/htmlsingle/#scheduling

<task:scheduler id="scheduler" pool-size="2"/>
person Anatoly Deyneka    schedule 02.11.2015
comment
Спасибо, Анатолий, на самом деле я не собираюсь увеличивать или уменьшать размер пула, но хочу завершить поток. Как я показал выше, конкретный поток находится в состоянии ожидания, а не завершен. каждый раз, когда задание запускается, оно создает новый поток с потухшим идентификатором потока, но поток никогда не завершается. Вы сталкивались с подобными ситуациями? - person Simon; 02.11.2015
comment
извините, я сделал ошибку, это не всегда отчетливо каждый раз. но это правда, что исходный поток кажется не завершенным. - person Simon; 02.11.2015
comment
количество незавершенных потоков зависит от конфигурации вашего пула. Потоки не завершаются по соображениям производительности - так работает пул потоков. Просто протестируйте его на количестве выполнений, превышающем размер вашего пула, и вы увидите, что потоки используются повторно. - person Anatoly Deyneka; 02.11.2015
comment
это приходило мне в голову раньше, но я понятия не имею, как настроить это при весенней загрузке с аннотацией. С xml или родным Java-исполнителем это намного проще. - person Simon; 02.11.2015
comment
Если вы все же хотите завершить потоки - используйте кешированный пул потоков. Создает пул потоков, который создает новые потоки по мере необходимости, но будет повторно использовать ранее созданные потоки, когда они будут доступны. Эти пулы обычно улучшают производительность программ, которые выполняют множество краткосрочных асинхронных задач. Вызовы на выполнение будут повторно использовать ранее созданные потоки, если они доступны. Если существующий поток недоступен, новый поток будет создан и добавлен в пул. Потоки, которые не использовались в течение шестидесяти секунд, завершаются и удаляются из кеша. - person Anatoly Deyneka; 02.11.2015
comment
перейдите по ссылке мой ответ, чтобы узнать, как его настроить (найдите лучший вариант для вашего приложения) - person Anatoly Deyneka; 02.11.2015