java - 一件有趣的事情发生了...... ExecutorCompletionService

标签 java executorservice futuretask inetaddress

我有一个用 java 编写的应用程序,需要找到网络上所有可访问的主机。

我使用 InetAddress.isReachable() 来执行此操作,超时为 2000 毫秒。

我查找当前本地机器的 IP 地址,并基于此我尝试访问以 1 - 255 结尾的其他 IP 地址,但丢失了本地机器的 IP 地址。

单线程一切正常,只是需要很长时间,因为大多数 IP 地址都无法访问,因为它们不存在,所以用完 2 秒超时。

为了加快速度(并尝试并发操作::Brian Goetz),我尝试使用 FutureCallable

一切都很顺利。

不过,我喜欢使用 ExecutorCompletionService 为我的用户提供响应速度更快的应用程序,这样他们就可以在结果可用时使用

Future<Reach> reachedFuture = completionService.take();

在具有以下配置的单处理器机器上运行它会导致仅识别四个可访问主机中的一个:

private static final int poolSize = 10;
private static final int maxPoolSize = 10;
private static final long keepAliveTime = 120;

private static final LinkedBlockingQueue<Runnable> queue
        = new LinkedBlockingQueue<Runnable>(20);

private static final ExecutorService executorService
        = new ThreadPoolExecutor(poolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue);

private static final CompletionService<Reach> completionService
        = new ExecutorCompletionService<Reach>(executorService);

在四核机器上将它改成这个也会导致它无法检测到所有可访问的主机:

private static final int poolSize
        = Math.max(2,Runtime.getRuntime().availableProcessors());

private static final int maxPoolSize
        = Math.max(2,Runtime.getRuntime().availableProcessors());

通过将 InetAddress.isReachable() 超时更改为 10 秒,最后的配置工作正常。

此外,通过在四核机器上按如下方式更改配置,还可以使其在 2 秒超时下工作:

private static final int poolSize = 2;
private static final int maxPoolSize = 2;

我是否遗漏了一些非常明显的原因?

是什么阻止 InetAddress.isReachable(2000) 检测我网络上的所有可访问主机?

为什么尝试运行多个 InetAddress.isReachable() 调用会失败?

最佳答案

所以我在我的 Mac 上写了一个小测试脚本,我不能让它失败——不管池的大小。我确实将 LinkedBlockingQueue 更改为无限制,否则我无法提交所有作业。此外,一段时间后 isReachable() 方法抛出一个 ConnectException,所以我必须专门处理它。这是您的代码@user423199 的问题吗?

代码如下:

http://pastie.org/2460991

我想知道你在什么操作系统上运行这个?某些 IP 堆栈可能不喜欢在同一进程中处理 ICMP 数据包的多个线程。我原以为所有现代操作系统都会对此很聪明,但这可能是一个潜在的问题。它也可能是 Java JRE 和操作系统堆栈之间的一些错误。

希望这对您有所帮助。

关于java - 一件有趣的事情发生了...... ExecutorCompletionService,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3986754/

相关文章:

java - 如何使用 map 进行多态 jackson 序列化

java - 在用户输入java上暂停线程池

java - ExecutorService 并在关闭后等待其他任务完成时接受新任务

java - ThreadPoolExecutor future 任务-Spring bean注入(inject)异常-spring-beans-2.0

Java:如何拖放到 TrayIcon 上?

Java - Highgui.imread 返回一个空矩阵

java - 是否可以限制 GlassFish(或底层 jvm 机器)中的端口号保留范围?

java - 如何使用预先存在的可运行对象,限制要创建的可运行对象的数量。?

Java 取消 Future - 如何等待完成?

java - 如何在使用 Future 接口(interface)时删除 java.util.concurrent.RejectedExecutionException