问题标签 [executorservice]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - 这需要同步吗?
在下面的课程中,我使用的是 singleThreadScheduledExecutor。我的问题是,我是否需要围绕对 dummyInt 和 dummyBoolean 的访问进行同步?
java - 发生 TimeoutException 时 JVM 不退出
我有代码需要做这样的事情
有一个类列表,每个类都有一些方法(比如说 execute())。我需要在每个类上调用该方法,并且每次调用都有一个固定的 timeOut。现在,该类的其中一个执行方法写得不好,导致超时,导致 jvm 不退出。我正在这样上课。
为什么jvm在代码执行完成后不退出?
我得到以下输出
第二类的执行超时,之后第三类的执行也超时。为什么第三类的执行超时?
执行完成后jvm不退出。是什么原因?还有为什么TestClass3
执行超时?
java - No output from exception
Why does this code not print an exception stack trace?
How can I get it to?
I would expect to see this:
java - java.util.concurrent.Future.get() 不返回
我有以下 Java 代码:
exeService
的一个实例在哪里
问题是myObject.doSomething()
永远不会返回,因此future.get()
永远不会返回。
但是,如果我将调用替换为这样submit
的调用execute
:
调用myObject.doSomething()
确实返回。我不知道这是否重要,但它doSomething()
是一种void
方法。
为什么使用时doSomething()
完成,使用execute
时却没有submit
?
另外,我不需要使用Future.get()
; 这似乎是最自然的方式。(我也遇到了同样的问题CountdownLatch
。)关键是我需要等待doSomething()
完成才能继续,并且由于复杂的原因我不会在这里讨论,我需要在单独的线程上启动它。如果有另一种可行的方法,那很好。
java - 限制 ExecutorService 队列中的每个 Runnable 类型之一
我有一个 Executors.newFixedThreadPool(1),我将几个不同的任务发送到(都实现了 Runnable),它们排队并按顺序运行正确吗?一次只允许每个任务中的一个运行或排队的最佳方法是什么?我想忽略所有发送到队列中的 ExecutorService 任务。
java - Future.get() 在什么情况下会抛出 ExecutionException 或 InterruptedException
我的代码片段:
我应该如何处理代码中的InterruptedException
and ExecutionException
?
在什么情况下会抛出这些异常?
java - Java 中最快的循环同步是什么(ExecutorService vs. CyclicBarrier vs. X)?
哪种 Java 同步结构可能为具有固定数量线程的并发迭代处理场景提供最佳性能,如下所述?在我自己试验了一段时间(使用 ExecutorService 和 CyclicBarrier)并且对结果有些惊讶之后,我将不胜感激一些专家的建议,也许还有一些新的想法。这里的现有问题似乎并不主要关注性能,因此这是一个新问题。提前致谢!
该应用程序的核心是一个简单的迭代数据处理算法,并行化以在运行 OS X 10.6 和 Java 1.6.0_07 的 Mac Pro 上的 8 个内核上分散计算负载。要处理的数据被分成 8 个块,每个块被馈送到一个 Runnable 以由固定数量的线程之一执行。将算法并行化相当简单,它在功能上可以按预期工作,但它的性能还不是我认为的那样。该应用程序似乎在系统调用同步上花费了很多时间,所以经过一些分析后,我想知道我是否选择了最合适的同步机制。
该算法的一个关键要求是它需要分阶段进行,因此线程需要在每个阶段结束时同步。主线程准备工作(非常低的开销),将其传递给线程,让它们处理它,然后在所有线程完成后继续,重新安排工作(同样非常低的开销)并重复循环。该机器专门用于此任务,垃圾收集通过使用预分配项目的每个线程池最小化,并且线程数可以固定(没有传入请求等,每个 CPU 核心只有一个线程)。
V1 - 执行服务
我的第一个实现使用了一个带有 8 个工作线程的 ExecutorService。该程序创建了 8 个任务来保存工作,然后让他们处理它,大致如下:
这在功能上运行良好(它应该做的),并且对于非常大的工作项,确实所有 8 个 CPU 都变得高度负载,正如处理算法所允许的那样(一些工作项将比其他工作项完成得更快,然后空闲) . 然而,随着工作项变得更小(并且这并不是真正在程序的控制之下),用户 CPU 负载急剧减少:
图例: - 块大小 = 工作项的大小(= 计算步数) - 系统 = 系统负载,如 OS X 活动监视器(红条) - 用户 = 用户负载,如 OS X 活动监视器(绿条) - 周期/秒 = 通过主 while 循环的迭代,越多越好
这里主要关注的领域是系统中花费的时间比例很高,这似乎是由线程同步调用驱动的。正如预期的那样,对于较小的工作项, ExecutorService.invokeAll() 将需要相对更多的努力来同步线程,而不是每个线程中正在执行的工作量。但是由于 ExecutorService 比这个用例需要的更通用(如果任务多于核心,它可以为线程排队任务),我认为可能会有一个更精简的同步结构。
V2 - 循环障碍
下一个实现使用 CyclicBarrier 在接收工作之前和完成之后同步线程,大致如下:
同样,这在功能上运行良好(它应该做的),并且对于非常大的工作项目,确实所有 8 个 CPU 都像以前一样变得高负载。然而,随着工作项变得更小,负载仍然急剧缩小:
对于大型工作项,同步可以忽略不计,性能与 V1 相同。但出乎意料的是,(高度专业化的)CyclicBarrier 的结果似乎比(通用)ExecutorService 的结果差得多:吞吐量(周期/秒)仅为 V1 的 1/4 左右。初步结论是,尽管这似乎是 CyclicBarrier 宣传的理想用例,但它的性能比通用的 ExecutorService 差得多。
V3 - 等待/通知 + CyclicBarrier
似乎值得尝试用简单的等待/通知机制替换第一个循环障碍 await():
同样,这在功能上运行良好(它做了它应该做的)。
小工作项的吞吐量仍然比 ExecutorService 差很多,但大约是 CyclicBarrier 的 2 倍。消除一个 CyclicBarrier 消除了一半的差距。
V4 - 忙等待而不是等待/通知
由于此应用程序是系统上运行的主要应用程序,并且如果内核不忙于工作项,内核无论如何都会空闲,为什么不在每个线程中尝试忙于等待工作项,即使这会不必要地旋转 CPU。工作线程代码更改如下:
在功能上也能很好地工作(它应该做的事情)。
对于小型工作项,这比 CyclicBarrier + wait/notify 变体进一步增加了 10% 的吞吐量,这并非微不足道。但它的吞吐量仍然比使用 ExecutorService 的 V1 低得多。
V5 - ?
那么对于这种(可能并不少见)问题的最佳同步机制是什么?我厌倦了编写自己的同步机制来完全替换 ExecutorService(假设它太通用了,必须有一些东西仍然可以取出以使其更高效)。这不是我的专业领域,我担心我会花费大量时间调试它(因为我什至不确定我的等待/通知和忙等待变体是否正确)以获得不确定的收益。
任何建议将不胜感激。
java - ExecutorService 在超时后中断任务
我正在寻找可以提供超时的ExecutorService实现。提交给 ExecutorService 的任务如果运行时间超过超时时间,就会被中断。实现这样的野兽并不是一项艰巨的任务,但我想知道是否有人知道现有的实现。
这是我根据下面的一些讨论得出的结论。任何意见?
java - 当新的线程将运行时,更大的线程池或额外的 ExecutorService?
ExecutorService
我有一个与Java中可能的 s 开销有关的问题。
本实现具有ExecutorService A
5个线程的容量。
- 它运行类型的线程
A
。 - 类型
A
线程执行一些数据库读取和写入。
现在,一个类型的线程B
将在一些类型的线程A
完成后运行。
- 将运行的类型
B
线程的数量有时会有所不同。 - 类型
B
线程做一些文件系统 IO(不是数据库)。
我也应该这样
- 添加一个新
ExecutorService
的来处理类型B
线程 - 还是我应该增加该线程的容量
ExecutorService A
并运行类型B
线程?
我认为 Java 有两个ExecutorService
s 可能会有一些额外的开销,但另一方面,线程总数会增加。这有关系吗?
java - 使用 Java 并发 API 对动态数据流进行建模的技术
编辑:这基本上是一个“如何在 Java 中正确实现数据流引擎”的问题,我觉得这不能用一个答案来充分回答(就像问“如何正确实现 ORM 层”并让某人写出Hibernate的细节或其他东西),所以认为这个问题“关闭”。
有没有一种优雅的方式来为 Java 中的动态数据流建模?通过数据流,我的意思是有各种类型的任务,这些任务可以任意“连接”,这样当一个任务完成时,后继任务将使用完成的任务输出作为输入并行执行,或者当多个任务完成时,它们的输出在后续任务中聚合(请参阅基于流的编程)。通过动态,我的意思是任务完成时后继任务的类型和数量取决于该已完成任务的输出,因此例如,如果任务 A 具有特定输出,则可能会生成任务 B,但如果具有特定输出,则可能会生成任务 C不同的输出。另一种说法是,每个任务(或一组任务)负责确定下一个任务是什么。
用于渲染网页的示例数据流:我有任务类型:文件下载器、HTML/CSS 渲染器、HTML 解析器/DOM 构建器、图像渲染器、JavaScript 解析器、JavaScript 解释器。
- HTML 文件的文件下载器任务
- HTML 解析器/DOM 构建器任务
- 每个嵌入文件/链接的文件下载器任务
- 如果是图像,图像渲染器
- 如果是外部 JavaScript,JavaScript 解析器
- JavaScript 解释器
- 否则,只需存储在 HTML 解析器任务中的某个 var/field 中
- 每个嵌入式脚本的 JavaScript 解析器
- JavaScript 解释器
- 等待上述任务完成,然后是 HTML/CSS 渲染器(显然不是最佳或完全正确,但这很简单)
- 每个嵌入文件/链接的文件下载器任务
- HTML 解析器/DOM 构建器任务
我并不是说解决方案需要一些全面的框架(事实上,越接近 JDK API 越好),我绝对不想要像 Spring Web Flow 或一些声明性标记或其他 DSL 这样重量级的东西.
更具体地说,我试图想出一种在 Java 中使用 Callables、Executors、ExecutorCompletionServices 以及可能还有各种同步器类(如 Semaphore 或 CountDownLatch)来对此进行建模的好方法。有几个用例和要求:
- 不要对任务将在哪个执行者上运行做出任何假设。事实上,为了简化,假设只有一个执行者。它可以是一个固定的线程池执行器,所以一个简单的实现可能会导致死锁(例如,想象一个任务提交另一个任务然后阻塞直到该子任务完成,现在想象这些任务中的几个用完所有线程)。
- 为简化起见,假设数据不是在任务之间流式传输(任务输出->后续任务输入)——完成任务和后续任务不必同时存在,因此后续任务的输入数据不会被前面的任务(因为它已经完成了)。
- 数据流“引擎”应该能够处理的只有几个操作:
- 一个任务可以排队更多任务的机制
- 在完成所有必需的输入任务之前,后继任务不会排队的机制
- 主线程(或其他不受执行程序管理的线程)阻塞直到流程完成的机制
- 一种机制,主线程(或其他不受执行程序管理的线程)阻塞直到某些任务完成
- 由于数据流是动态的(取决于任务的输入/状态),这些机制的激活应该发生在任务代码中,例如,Callable 中的代码本身负责将更多的 Callables 排队。
- 数据流“内部”不应该暴露给任务(Callables)本身——只有上面列出的操作应该对任务可用。
- 请注意,所有任务的数据类型不一定相同,例如文件下载任务可能接受文件作为输入,但会输出字符串。
- 如果一个任务抛出一个未捕获的异常(表明一些致命错误,需要停止所有数据流处理),它必须尽快传播到启动数据流的线程并取消所有任务(或者像致命错误处理程序这样更奇特的东西)。
- 任务应尽快启动。这与之前的要求一起应该排除简单的 Future 轮询 + Thread.sleep()。
- 作为奖励,我希望数据流引擎本身在每次任务完成时或自上次任务完成后 X 时间内没有完成时执行一些操作(如日志记录)。就像是:
ExecutorCompletionService<T> ecs; while (hasTasks()) { Future<T> future = ecs.poll(1 minute); some_action_like_logging(); if (future != null) { future.get() ... } ... }
是否有直接的方法可以使用 Java 并发 API 完成所有这些操作?或者,如果无论 JDK 中有什么可用的东西都会变得复杂,那么是否有一个轻量级的库可以满足要求?我已经有一个适合我的特定用例的部分解决方案(它在某种程度上作弊,因为我使用了两个执行程序,而且你知道,它与我上面给出的网络浏览器示例完全无关),但我'希望看到一个更通用和优雅的解决方案。