3

我有一个将作业分派到线程池的主线程。我正在使用 Java 的 Executor 框架。

从分析器(VirtualVM)我可以看到每个线程的活动:我可以看到主线程正在等待很多(因为执行程序的队列有上限),这意味着执行程序的队列大部分时间都是满的。然而,执行者的线程并不像我想象的那么忙。他们中的大多数人的等待时间为 75%。在 virtualVM 中,它说它在 Monitor 上等待。

谁能解释为什么会这样?为什么执行程序线程会等待,而仍有大量工作可做?以及如何提高执行器的性能?从而提高整体性能?关于执行者等待监视器的更多细节会很棒。

在工作人员中运行的工作只是一些计算,它不依赖于其他任何东西,也不与任何其他线程通信(不同步),除了最后,它将数据放入数据库,使用它自己的连接.

4

4 回答 4

3

如果满足以下条件,并行执行将产生比同步执行更好的结果:

  1. 要完成的工作彼此独立(没有或很少且非常短的关键部分)

  2. 每个单独执行的工作都需要足够的时间来弥补线程启动/执行器的内部同步

  3. 这项工作不使用相同的资源 - 例如从同一个磁盘读取多个文件可能会比顺序读取它们要慢。

  4. 您实际上有足够的系统资源(处理器内核、内存、网络速度)可以一次使用

于 2013-05-08T14:08:12.220 回答
1

线程化并不意味着所有线程将一直并行工作。由于各种原因,线程肯定会进入等待状态,主要取决于调度程序如何为每个线程分配 CPU。您的线程类中是否有一些同步代码?如果是,那么如果一个线程正在执行同步方法,那么所有其他线程都必须等待。如果同步代码过多,则线程等待时间会增加。

于 2013-05-08T14:02:25.400 回答
0

进行线程转储后,事实证明是数据库层进行了同步。Hibernate 的序列生成器是同步的。

"pool-2-thread-1" - Thread t@13
   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" t@23
    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)
于 2013-05-08T15:14:41.020 回答
0

线程由调度程序调度以分配 cpu 周期来运行它们,这意味着如果机器有 4 个 cpu,一次只能并行运行 4 个线程,因此其他线程必须等待调度程序为它们分配 cpu。

于 2013-05-08T14:08:35.100 回答