【问题标题】:Java's ExecutorService performanceJava 的 ExecutorService 性能
【发布时间】:2013-05-08 13:57:19
【问题描述】:

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

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

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

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

【问题讨论】:

  • 它可能是重复的:stackoverflow.com/questions/7155608/…
  • 你在做什么工作?从 Job 对象发布代码。发布关键部分代码。
  • 您确定他们在等待工作吗?他们更有可能正在等待其他锁。
  • “它在 Monitor 上等待。” => 你似乎正在使用锁或同步语句,这是你的瓶颈......
  • 有没有办法查看他们正在等待哪个显示器?我也怀疑是executor的内部监视器。

标签: java multithreading concurrency executorservice java.util.concurrent


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      进行线程转储后,发现是数据库层进行了同步。 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)
      

      【讨论】:

      • 根据您提供的信息,我们无法猜到这一点。只需与数据库建立一些连接,您的问题就解决了。然后数据库将成为瓶颈......
      • 我不知道hibernate会做那么愚蠢的事情..而不是发送记录并要求数据库计算记录的序列,它首先询问数据库序列(这将需要同步)然后将记录与序列值一起发送。
      • 必须这样做。当涉及到关系时,它允许他重新排序事务中的插入。
      【解决方案4】:

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

      【讨论】:

      • 积极竞争 CPU 周期的线程可以运行,而不是等待监视器
      • 感谢纠正我的误解:)我找到了java线程状态的一个greate状态机图:uml-diagrams.org/examples/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-01
      • 2016-05-07
      • 2012-07-31
      • 2014-11-15
      • 2010-09-29
      • 1970-01-01
      相关资源
      最近更新 更多