3

У меня есть основной поток, который отправляет задания в пул потоков. Я использую инфраструктуру Executor Java.Производительность ExecutorService Java

Из профайлера (VirtualVM) Я вижу активность каждого потока: я вижу, что основной поток ждет много (потому что очередь исполнителя имеет верхний предел), что означает, что очередь исполнителя заполняется большую часть времени. Однако потоки исполнителя не так заняты, как я думал. Большинство из них имеют время ожидания 75%. В virtualVM говорится, что он ждет Монитора.

Может ли кто-нибудь объяснить, почему это происходит? почему бы потоки исполнителей ждать, пока есть еще много возможностей для работы? И как улучшить производительность исполнителя? таким образом, чтобы улучшить производительность в целом? Более подробная информация о ожидании исполнителя на мониторе будет отличной.

Работа, выполняемая рабочими, - это всего лишь некоторые вычисления, которые не зависят ни от чего другого и не сообщаются ни с каким другим потоком (без синхронизации), за исключением того, что в конце они помещают данные в базу данных, используя это собственное соединение.

+0

Это может быть дубликатом: http://stackoverflow.com/questions/7155608/executorservice-slow-multi-thread-performance?rq=1 –

+1

Какую работу вы делаете? Почтовый код из объектов Job. Введите критический код раздела. – Dariusz

+1

Вы уверены, что они ждут работы? Скорее всего, они ждут какой-то другой замок. – Gray

ответ

0

После выполнения дампа потока получается, что это уровень базы данных, который имеет синхронизацию. Синхронизирован генератор последовательности Hibernate.

"pool-2-thread-1" - Thread [email protected] 
    java.lang.Thread.State: BLOCKED 
    at org.hibernate.id.SequenceHiLoGenerator.generate(SequenceHiLoGenerator.java:73) 
    - waiting to lock <61fcb35> (a org.hibernate.id.SequenceHiLoGenerator) owned by "pool-2-thread-5" [email protected] 
    at org.hibernate.internal.StatelessSessionImpl.insert(StatelessSessionImpl.java:117) 
    at org.hibernate.internal.StatelessSessionImpl.insert(StatelessSessionImpl.java:110) 
    at ac.uk.ebi.kraken.unisave.storage.impl.HibernateStorageEngine.saveEntryIndex(HibernateStorageEngine.java:269) 
    at ac.uk.ebi.kraken.unisave.storage.impl.EntryStoreImpl.storeEntryIndex(EntryStoreImpl.java:302) 
    at ac.uk.ebi.kraken.unisave.impl.MTEntryIndexLoader$EntryIndexLoader.run(MTEntryIndexLoader.java:129) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 
    at java.lang.Thread.run(Thread.java:679) 

    Locked ownable synchronizers: 
    - locked <3d360c93> (a java.util.concurrent.ThreadPoolExecutor$Worker) 
+2

Мы не могли догадаться, что с информацией, которую вы нам дали. Просто сделайте несколько соединений с БД, и ваша проблема исправлена. И тогда БД станет узким местом ... – Dariusz

+0

Я понятия не имею, что спящий режим будет делать что-то глупое. Вместо того, чтобы отправлять запись и запрашивать базу данных для вычисления последовательности для записи, сначала запрашивает последовательность базы данных (которая будет нужна синхронизация), затем отправьте запись вместе со значением последовательности. – Wudong

+0

It * есть * сделать таким образом. Это позволяет ему переупорядочивать вставки в транзакции, когда есть отношения. – gizmo

1

Threading не означает, что все потоки будут работать параллельно. Потоки, несомненно, перейдут в состояние ожидания по разным причинам, в основном, зависят от того, как планировщик назначает процессор каждому из них. Есть ли какой-то синхронизированный код в вашем классе потоков? Если да, то если один поток выполняет синхронизированный метод, тогда все остальные потоки должны ждать. Если слишком много синхронизированного кода, тогда время ожидания потоков увеличится.

+0

Отсутствие синхронизации у рабочих. – Wudong

3

Параллельное выполнение даст значительно лучшие результаты, синхронное исполнение, если:

  1. работа, чтобы сделать независимо друг от друга (нет или мало и очень короткие критические секции)

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

  3. Работа не использует один и тот же ресурс - например, чтение нескольких файлов из одного и того же диск, вероятно, будет медленнее, чем чтение их последовательно.

  4. вы на самом деле достаточно системных ресурсов (процессорных ядер, памяти, скорость сети), чтобы использовать сразу

0

Thread планируется планировщиком назначить циклов центрального процессора, чтобы запустить их, это означает, что если машина имеет 4 cpus, одновременно может выполняться только 4 потока, поэтому другим потокам приходится ждать, пока планировщик назначит им CPU.

+1

Темы, активно конкурирующие за циклы процессора, будут RUNNABLE, не ожидая на мониторе –

+0

спасибо за исправление моего недоразумения :) Я нахожу графическую машину с графическим состоянием для состояния Java-потока: http://www.uml-diagrams.org/examples/java -6-thread-state-machine-diagram-example.html – ltebean

Смежные вопросы