一件有趣的事情发生了……executorCompletionservice
-
10-10-2019 - |
题
我有一个用Java编写的应用程序,需要在网络上找到所有可触及的主机。
我用 InetAddress.isReachable()
用2000毫秒的超时来完成此操作。
我查找当前本地计算机的IP地址,并根据我试图达到1-255的其他IP地址缺少本地计算机IP地址。
所有这些都可以正常工作,只需要很长时间,因为大多数IP地址都无法到达,因为它们不存在,因此请使用2秒的超时。
为了加快事情的速度(并尝试在行动中进行并发:: Brian Goetz)我尝试使用 Future
和 Callable
等等
一切也很好。
但是我幻想使用 ExecutorCompletionService
为了给我的用户一个更响应迅速的应用程序,因此他们可以看到结果
Future<Reach> reachedFuture = completionService.take();
在具有以下配置的单个处理器机器上运行此功能仅导致四个可访问主机中的1个被识别:
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);
将其更改为Quad Core机器也使其无法检测到所有可触及的主机:
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秒使最后一个配置工作正常。
同样,通过更改Quad Core机器上的配置,也使其与2秒的超时合作:
private static final int poolSize = 2;
private static final int maxPoolSize = 2;
我是否错过了很明显的原因,为什么会发生这种情况?
什么停止 InetAddress.isReachable(2000)
从检测网络上的所有可触及的主机?
为什么尝试多次运行 InetAddress.isReachable()
电话失败了?
解决方案
因此,我在Mac上写了一个小测试脚本,我无法失败 - 不管游泳池的大小如何。我确实改变了 LinkedBlockingQueue
要无限,否则我将无法提交所有工作。另外,过了一会儿 isReachable()
方法正在扔 ConnectException
因此,我必须具体处理。这是您的代码 @user423199的问题吗?
这是代码:
我想知道您正在运行什么操作系统?某些IP堆栈可能不喜欢在同一过程中执行ICMP数据包的多个线程。我本来以为所有现代操作系统都会很明智,但这可能是一个潜在的问题。这也可能是Java JRE和OS堆栈之间的错误。
希望这可以帮助。