我有一个主线程,它将作业分派到线程池。我正在使用Java的Executor框架。
从分析器(VirtualVM)我可以看到每个线程的活动:我可以看到主线程正在等待很多(因为执行器的队列有上限),这意味着执行器的队列大部分时间都是满的。然而,执行者的线程并不像我想象的那么忙。大多数的等待时间是75%。在virtualVM中,它说它等待Monitor。
有谁能解释一下为什么会这样吗?为什么执行线程在仍然有大量工作可做的情况下要等待呢?如何提高遗嘱执行人的绩效?从而提高整体性能?更多关于执行者在监视器上等待的细节将是伟大的。
工作在工人中运行只是一些计算,它不依赖于其他任何东西,也不与任何其他线程通信(没有同步),除了最后,它把数据放在数据库中,使用它自己的连接。
如果:
并行执行将产生明显更好的结果:要做的工作是相互独立的(没有或很少且非常短的临界段)
每个单独执行的工作需要足够的时间来弥补线程启动/执行器的内部同步
工作不使用相同的资源-例如,从同一个磁盘读取多个文件可能比顺序读取它们要慢。
你实际上有足够的系统资源(处理器内核,内存,网络速度)一次使用
线程化并不意味着所有线程都是并行工作的。由于各种原因,线程肯定会进入等待状态,这主要取决于调度器如何为每个线程分配CPU。在线程类中是否有一些同步代码?如果是,那么如果一个线程正在执行同步方法,那么所有其他线程都必须等待。如果有太多的同步代码,那么线程等待时间将会增加。
在执行线程转储之后,结果是数据库层具有同步。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)
线程由调度器调度分配cpu周期来运行,这意味着如果机器有4个cpu,一次只能并行运行4个线程,因此其他线程必须等待调度器为它们分配cpu