a funny thing happens... ExecutorCompletionService
I have an application written in java that needs to find all the reachable hosts on the network.
I use InetAddress.isReachable()
to do this with a timeout of 2000 milliseconds.
I look up the current local machine's IP address and based on that I attempt to reach the other IP addresses that end 1 - 255 missing out the local machines IP address.
It all works fine single threaded, just takes a long time as most of the IP addresses are not reachable as they do not exist so use up the 2 second timeout.
To speed things up (and try out concurrency in action :: Brian Goetz) i tried using Future
and Callable
etc.
This all went fine as well.
However i fancied using ExecutorCompletionService
to give my users a more responsive application, so they could see results as they came available using
Future<Reach> reachedFuture = completionService.take();
Running this on a singleprocessor machine with the following config causes only 1 of the four reachable hosts to be identified:
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);
Changing it to this on a quad core machine also made it fail to detect all the reachable hosts:
private static final int poolSize
= Math.max(2,Runtime.getRuntime().availableProcessors());
private static final int maxPoolSize
= Math.max(2,Runtime.getRuntime().availableProcessors());
By changing the InetAddress.isReachable()
timeout to 10 seconds made the last config work ok.
Also by changing the config as follows on the quad core machine also made it work with a 2 second timeout:
private static final int poolSize = 2;
private static final int maxPoolSize = 2;
Am I missing something very obvious why this happens?
What stops InetAddress.isReachable(2000)
from detecting all the reachable hosts on my network?
Why does attempting to run multiple InetAddress.isReachable()
开发者_运维技巧calls fail?
So I wrote a little test script on my Mac and I can't get it to fail -- regardless of the size of the pool. I did change the LinkedBlockingQueue
to be unlimited otherwise I couldn't submit all of the jobs. Also, after a while the isReachable()
method was throwing a ConnectException
so I had to handle that specifically. Is this the problem with your code @user423199?
Here's the code:
http://pastie.org/2460991
I'm wondering what OS you are running this on? Certain IP stacks may not like multiple threads doing ICMP packets within the same process. I would have thought that all modern operating systems would be smart about that but this may be a potential issue. It also may be some bug between the Java JRE and the OS stack.
Hope this helps.
精彩评论