2010-10-21 1 views
3

У меня есть приложение, написанное в java, которое должно найти все доступные хосты в сети.Происходит забавная вещь ... ExecutorCompletionService

Я использую InetAddress.isReachable(), чтобы сделать это с тайм-аутом в 2000 миллисекунд.

Я просматриваю IP-адрес текущего локального компьютера и на основании этого пытаюсь достичь других IP-адресов, заканчивающихся 1 - 255, пропускающих IP-адрес локальных компьютеров.

Все работает отлично однопоточно, просто занимает много времени, так как большинство IP-адресов недоступны, так как они не существуют, поэтому используйте 2-секундный тайм-аут.

Чтобы ускорить процесс (и опробовать параллелизм в действии :: Brian Goetz) я попытался с помощью Future и Callable т.д.

Это все шло хорошо, как хорошо.

Однако я воображал, используя ExecutorCompletionService, чтобы дать своим пользователям более отзывчивое приложение, чтобы они могли видеть результаты, как они пришли доступны с помощью

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

Запуска этого на singleprocessor машине со следующей конфигурацией вызывает только один из четыре достижимых хосты должны быть определены:

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() не выполняется?

+2

Вы пытались использовать 'Executors.newSingleThreadExecutor()', чтобы увидеть, является ли это кодом потока, вызывающим проблему? Это по крайней мере направит нас в правильном направлении. –

ответ

1

Итак, я написал небольшой скрипт сценария на своем Mac, и я не могу заставить его сбой - независимо от размера пула. Я изменил LinkedBlockingQueue, чтобы быть неограниченным, иначе я не смог бы отправить все задания. Кроме того, через некоторое время метод isReachable() выбрасывал ConnectException, поэтому мне пришлось обрабатывать его конкретно. Это проблема с вашим кодом @ user423199?

Вот код:

http://pastie.org/2460991

мне интересно, что ОС вы работаете это на? Некоторым стекам IP может не нравиться несколько потоков, выполняющих ICMP-пакеты в рамках одного процесса. Я бы подумал, что все современные операционные системы будут умны в этом, но это может быть потенциальной проблемой. Это также может быть некоторая ошибка между Java JRE и стекю ОС.

Надеюсь, это поможет.

+0

«Некоторые стеки IP могут не нравиться нескольким потокам, выполняющим ICMP-пакеты в одном и том же процессе»: не будет ли это ошибкой в ​​реализации «InetAddress.isReachable()» для этой платформы? Java API не ограничивает его нитью. – Raedwald

+0

Возможно или ограничение в стеке IP ОС. Я размышлял на самом деле. Не уверен, что это случится, но я подумал, что упомянул об этом. – Gray