我正在编写一个必须发出数千个网络请求的实用程序。每个请求只收到一个小数据包作为响应(类似于 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)));
}
}
...然后我将队列中的所有元素出列并将结果放入所需的数据结构中:
int[] result = int[65536]
while(!futures.isEmpty()) {
try {
results[i] = futures.remove().get();
} catch (Exception e) {
addresses[i] = -1;
}
}
我的第一个问题是:这是跟踪所有线程的合理方法吗?如果线程 X 需要一段时间才能完成,那么许多其他线程可能会在 X 之前完成。线程池是否会在等待打开的插槽时耗尽自身,或者ExecutorService
对象是否会以这样的方式管理池,将已完成但尚未处理的线程移出可用插槽,以便其他线程开始?
我的第二个问题是我可以使用哪些准则来找到进行这些调用的最佳线程数?我什至不知道这里的数量级指导。我知道它在 256 个线程上工作得很好,但似乎在 1024 个线程上花费的总时间大致相同。CPU 利用率徘徊在 5% 左右,因此这似乎不是问题。有了这么多线程,我应该查看哪些指标来比较不同的数字?显然,处理批处理的总时间,每个线程的平均时间......还有什么?内存是这里的问题吗?