当前位置: 首页 > 知识库问答 >
问题:

Java ExecutorService-有时比顺序处理慢?

楚洋
2023-03-14

我正在编写一个简单的实用程序,它接受可调用任务的集合,并并行运行它们。希望所用的总时间比最长的任务所用的时间少得多。该实用程序还添加了一些错误处理逻辑--如果任何任务失败,并且该失败可以被视为“可重试”(例如超时或用户指定的异常),那么我们直接运行该任务。

我已经围绕ExecutorService实现了这个实用程序。有两个部分:

  1. 向ExecutorService提交()所有可调用任务,存储未来对象。
  2. 在for循环中,get()是每个future的结果。如果出现异常,请执行“可重试”逻辑。

我编写了一些单元测试,以确保使用此实用程序比按顺序运行任务更快。对于每个测试,我会生成一定数量的可调用的,每个可调用的本质上是在一个范围内执行一个thread.sleep()的随机时间量。我尝试了不同的超时、不同数量的任务等,该实用程序的性能似乎优于顺序执行。

但当我将它添加到需要这种实用程序的实际系统中时,我看到的结果非常多变--有时并行执行更快,有时更慢,有时更快,但仍然要比最长的单个任务花费更多的时间。

我做错了吗?我知道ExecutorService有invokeAll(),但它吞噬了底层异常。我还尝试使用CompletionService按任务完成的顺序获取任务结果,但它表现出了或多或少的相同行为。我现在正在读关于锁闩和屏障的书--这是解决这个问题的正确方向吗?

共有1个答案

充小云
2023-03-14

我编写了一些单元测试,以确保使用此实用程序比按顺序运行任务更快。对于每个测试,我会生成一定数量的可调用的,每个可调用的本质上是在一个范围内的随机时间内执行一个thread.sleep()

是的,这肯定不是一个公平的测试,因为它既没有使用CPU也没有使用IO。我当然希望并行Hibernate比串行Hibernate运行得更快。:-)

但是当我将它添加到需要这种实用程序的实际系统中时,我看到的结果是很不一样的

对啊。线程应用程序是否比串行应用程序运行得更快,这在很大程度上取决于许多因素。特别是IO绑定的应用程序,由于受到IO通道的绑定,因此确实无法进行并发操作,因此性能不会提高。应用程序需要的处理越多,将其转换为多线程的过程就越困难。

我做错了吗?

没有更多的细节很难知道。您可以考虑使用并发运行的线程数。如果要处理大量作业,则不应使用executos.newCachedThreadPool(),而应根据体系结构的CPU数量优化newFixedSizethreadPool(...)

您可能还想看看是否可以将IO操作隔离在几个线程中,而将处理隔离到其他线程中。比如一个输入线程读取文件,一个输出线程(或两个线程)写入数据库或其他东西。因此,对于不同类型的任务,多个大小的池可能比使用单个线程池更好。

尝试使用CompletionService按任务完成的顺序提取任务结果

如果您正在重试操作,那么使用completionservice是正确的方法。当作业完成并抛出异常(或返回失败)时,它们可以被重新启动并立即放回线程池中。我看不出有什么理由你的表现问题会是因为这个。

 类似资料:
  • 22.2.3 DispatcherServlet的处理顺序 在设立了一个DispatcherServlet并且收到一个对该特定DispatcherServlet的请求之后,这个DispatcherServlet将按如下顺序开始处理该请求: 搜索WebApplicationContext,并将其绑定为请求中的一个属性,以使控制器和进程中的其他元素能够使用它。默认情况下,绑定在DispatcherSe

  • 我每个websocket接收几十条消息,这些消息可能只差几毫秒就能到达。我需要用操作来处理这些数据,这些操作有时会花费一些时间(例如,在DB中的插入)。为了处理接收到的新消息,必须完成对前一个消息的处理。 我的第一个想法是用Node.js Bull(用Redis)准备一个队列,但恐怕太长了,无法运行。这些消息的处理必须保持快速。 我尝试使用JS迭代器/生成器(直到现在我还从未使用过),我测试了如下

  • 当我尝试以下代码时 我还是并行编程的新手。我怎么能得到一个并行版本比顺序版本更快?

  • 问题内容: 通过标准DOM处理XML时,不能保证属性顺序在重新序列化之后。最后,这是我在使用标准java XML Transform API序列化输出时刚刚意识到的。 但是我确实需要保持秩序。我想知道在Java上是否有可能保持通过DOM API处理的XML文件的属性的原始顺序,或以任何方式强制执行该顺序(可能通过使用替代的序列化API来让你进行设置)一种财产)。就我而言,处理减少了用一堆属性来更改

  • 问题内容: 我正在尝试在Java项目上运行Dagger 2和Lombok。当然,龙目岛必须首先运行,但是它的确存在取决于机会。起初,我怀疑我可以通过类路径中库jar的相应位置来指定顺序,但是该顺序显然被忽略了。 有没有办法指定它们以某种方式运行的顺序,还是我必须忍受不能合并两个AP的情况? 我制作了一个SSCCE测试用例。 一个简单的&就足以说明问题- 如果在App.java中注释第18行和取消注

  • 我正在尝试在我的Java项目中运行Dagger2和Lombok。当然,龙目岛必须先跑,但它是否真的跑了,似乎要看机会。起初,我怀疑我可以通过库jar在类路径中各自的位置来指定顺序,但这个顺序显然被忽略了。 有没有一种方法可以指定它们运行的顺序,或者我只能忍受不能组合两个AP? 我已经生成了一个SSCCE测试用例。 一个简单的&就足以说明这个问题--如果您在app.java中注释第18行而取消注释第