sea*_*olf 10 java networking multithreading akka
我正在编写一个必须生成数千个网络请求的实用程序.每个请求只接收一个响应的小数据包(类似于ping),但可能需要几秒钟才能完成.处理每个响应在一个(简单)代码行中完成.
这样做的最终结果是计算机不受IO限制,受文件系统限制或受CPU限制,它仅受响应延迟的约束.
这类似于,但不一样有一种方法可以确定理想的线程数?和Java最好的方法来确定最佳线程数[重复] ...主要的区别是我只受延迟的约束.
我正在使用一个ExecutorService对象来运行线程和一个Queue<Future<Integer>>跟踪需要检索结果的线程:
ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
Queue<Future<Integer>> futures = new LinkedList<Future<Integer>>();
for (int quad3 = 0 ; quad3 < 256 ; ++quad3) {
for (int quad4 = 0 ; quad4 < 256 ; ++quad4) {
byte[] quads = { quad1, quad2, (byte)quad3, (byte)quad4 };
futures.add(executorService.submit(new RetrieverCallable(quads)));
}
}
Run Code Online (Sandbox Code Playgroud)
...然后我将队列中的所有元素出列,并将结果放入所需的数据结构中:
int[] result = int[65536]
while(!futures.isEmpty()) {
try {
results[i] = futures.remove().get();
} catch (Exception e) {
addresses[i] = -1;
}
}
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是:这是跟踪所有线程的合理方法吗?如果线程X需要一段时间才能完成,许多其他线程可能会在X之前完成.线程池是否会耗尽自己等待打开的插槽,或者ExecutorService对象是否会以这样的方式管理池:已经完成但尚未处理的线程被移出可用的插槽,以便我的其他线程开始?
我的第二个问题是我可以使用什么指南来查找进行这些调用的最佳线程数?我甚至不知道这里的数量级指导.我知道它可以很好地运行256个线程,但似乎整个时间与1024个线程大致相同.CPU利用率徘徊在5%左右,因此这似乎不是问题.有了这么大的线程,我应该考虑比较不同数字的所有指标是什么?显然处理批次的总时间,每个线程的平均时间......还有什么?记忆是个问题吗?
小智 7
它会震撼你,但你不需要I/O的任何线程(数量上,这意味着0个线程).你研究过多线程不会增加你的网络带宽是很好的.现在,是时候知道线程进行计算了.他们没有进行(高延迟)通信.通信由网络适配器执行,网络适配器是另一个与CPU并行运行的进程.在网络适配器完成其工作之前,分配一个线程(查看由这位声称您需要1个线程的绅士列出的分配的资源)只是睡眠是愚蠢的.I/O不需要线程=你需要0个线程.
为计算分配线程与I/O请求并行是有意义的.线程数量取决于计算通信比率,并受CPU中核心数量的限制.
对不起,我不得不说,尽管你肯定暗示了阻止I/O的承诺,但很多人都不理解这个基本的东西.听取建议,使用异步I/O,你会发现问题不存在.
正如您所提到的链接答案中提到的,Brian Goetz在他的文章中已经涵盖了这一点.
他似乎暗示在您的情况下,建议您在提交线程计数之前收集指标.
调整池大小
调整线程池的大小主要是避免两个错误:线程太少或线程太多....
线程池的最佳大小取决于可用处理器的数量以及工作队列上任务的性质....
对于可能等待I/O完成的任务 - 例如,从套接字读取HTTP请求的任务 - 您将希望将池大小增加到超过可用处理器的数量,因为并非所有线程都能正常工作每时每刻.使用分析,您可以估计典型请求的等待时间(WT)与服务时间(ST)的比率.如果我们将此比率称为WT/ST,对于N处理器系统,您将需要大约N*(1 + WT/ST)线程来保持处理器的充分利用.
我的重点.