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

时间:2010-10-21 11:07:53

标签: 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()调用失败?

1 个答案:

答案 0 :(得分:1)

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

以下是代码:

  

http://pastie.org/2460991

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

希望这有帮助。