Java的FutureTask可组合性

我尝试使用Java的FutureTask,Future,Runnable,Callable和ExecutorService类型.

构建这些构建块的最佳实践是什么?

鉴于我有多个FutureTasks并且我想按顺序执行它们.

当然,我可以创建另一个FutureTask,它按顺序提交/等待每个子任务的结果,但我想避免阻塞调用.

另一种选择是让这些子任务在完成时调用回调,并在回调中安排下一个任务.但是走这条路,如何创建一个合适的外部FutureTask对象,它也处理子任务中的异常而不会产生那么多的样板?

在这里想念一下吗?

最佳答案
非常重要的事情,虽然通常没有在教程中描述:

要在ExecutorService上执行的Runnables不应该阻止.这是因为每个阻塞都会关闭一个工作线程,如果ExecutorService的工作线程数量有限,则存在陷入死锁(线程饥饿)的风险,如果ExecutorService具有无限数量的工作线程,则存在风险内存耗尽.阻塞任务中的操作只会破坏ExecutorService的所有优点,因此仅在常用线程上使用阻塞操作.

FutureTask.get()是阻塞操作,因此可以在普通线程上使用,而不是在ExecutorService任务中使用.也就是说,它不能用作构建块,而只能将执行结果传递给主线程.

从任务构建执行的正确方法是在下一个任务的所有输入数据都准备就绪时启动下一个任务,这样任务就不必阻止等待输入数据.因此,您需要一种存储中间结果的门,并在所有参数到达时启动新任务.因此,任务不会明确地开始其他任务.因此,由参数的输入套接字和用于计算它们的Runnable组成的门可以被视为用于ExcutorServices上的计算的正确构建块.

方法称为数据流或工作流(如果无法动态创建门).

像Akka这样的Actor框架使用这种方法但是受限制的事实是actor是一个带有单输入套接字的门.

我写了一个真正的数据流库,发布于https://github.com/rfqu/df4j.

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...