一个有趣的事情发生了… ExecutorCompletionService

我有一个用java编写的应用程序,需要找到网络上所有可访问的主机。 我使用
InetAddress.isReachable()
来执行此操作,超时为2000毫秒。 我查找当前本地计算机的IP地址,并在此基础上尝试访问结束1 - 255的其他IP地址,错过本地计算机的IP地址。 这一切都工作得很好单线程,只需要很长时间,因为大多数IP地址不可访问,因为它们不存在,所以用完2秒超时。 为了加快速度(尝试并发行动:: Brian Goetz)我尝试使用
Future
Callable
等。 这一切都很顺利。 不过我觉得使用
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和OS堆栈之间的一些错误。 希望这可以帮助。     

要回复问题请先登录注册