Подтвердить что ты не робот

ОЖИДАНИЕ на sun.misc.Unsafe.park(родной метод)

Одно из моих приложений зависает под некоторым периодом работы под загрузкой, кто-нибудь знает, что может вызвать такой вывод в jstack:

"scheduler-5" prio=10 tid=0x00007f49481d0000 nid=0x2061 waiting on condition [0x00007f494e8d0000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000006ee117310> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1085)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)

Я вижу это много в выводе jstack, когда он зависает.

Я сильно использую Spring @Async и карты, синхронизированные карты и ehcache.

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

Я нашел этот пост https://stackoverflow.com/info/23992787/parking-to-wait-for-0xd8cf0070-a-java-util-concurrent-locks-abstractqueueds, но это не очень полезно в моем случае.

4b9b3361

Ответ 1

unsafe.park почти такой же, как thread.wait, за исключением того, что он использует код, специфичный для архитектуры (поэтому причина "небезопасна" ). небезопасно не предоставляется общедоступно, но используется в внутренних библиотеках Java, где код, специфичный для архитектуры, будет предлагать значительные преимущества оптимизации. Он много использовал для объединения потоков.

Итак, чтобы ответить на ваш вопрос, весь поток работает, что-то ждет, на самом деле он не использует какой-либо процессор. Учитывая, что ваша исходная трассировка стека показывает, что вы используете блокировку, я бы предположил, что в вашем случае происходит тупик.

Да, я знаю, что вы почти наверняка уже решили эту проблему. Тем не менее, вы являетесь одним из лучших результатов, если кто-то googles sun.misc.unsafe.park. Я полагаю, что ответ на этот вопрос может помочь другим понять, что этот метод, который, кажется, использует весь их процессор.

Ответ 2

Из трассировки стека ясно, что поток ThreadPoolExecutor > Worker запущен и ожидает, что задача будет доступна в BlockingQueue (DelayedWorkQueue), чтобы выбрать задачу и выполнить. Таким образом, этот поток будет находиться в состоянии WAIT только до тех пор, пока как получить СИГНАЛ из потока издателя.

Ответ 3

У меня была аналогичная проблема, и после предыдущих ответов (спасибо!) я смог найти и найти, как правильно обрабатывать terminkison ThreadPoolExecutor.

В моем случае это просто исправить мое прогрессивное увеличение похожих заблокированных потоков:

  • Я использовал ExecutorService::awaitTermination(x, TimeUnit) и ExecutorService::shutdownNow() (если необходимо) в моем предложении finally.
  • Для получения информации я использовал следующие команды для определения количества потоков и списка заблокированных потоков:

    ps -u javaAppuser -L | wc -l

    jcmd `ps -C java -o pid =` Thread.print → threadPrintDayA.log

    jcmd `ps -C java -o pid =` Thread.print → threadPrintDayAPlusOne.log

    cat threadPrint *.log | grep "pool-" | wc -l

Ответ 4

Если вам нужны входные ворота для низкоуровневого программирования в Java, возможно, вам придется использовать

  • JNI, который требует от вас знания некоторого C language и быстро приведет к коду, тесно связанному с конкретной платформой.
  • sun.misc.Unsafe, однако есть и другая альтернатива низкоуровневому программированию на платформе Java с использованием Java API, хотя эта альтернатива не рекомендуется.

Парк/Распаркуйте

В API Unsafe есть два увлекательных метода, которые используются JVM для переключения потоков контекста. Когда поток ожидает какого-либо действия, JVM может заблокировать этот поток с помощью метода park() из класса Unsafe.

Он очень похож на метод Object.wait(), но он вызывает собственный код ОС, что позволяет использовать некоторые особенности архитектуры для достижения максимальной производительности.

Когда поток заблокирован и его необходимо снова запустить, JVM использует метод unpark(). Мы часто видим эти вызовы методов в дампах потоков, особенно в приложениях, использующих пулы потоков.

Подробнее здесь, здесь