случается забавная вещь ... ExecutorCompletionService - PullRequest
3 голосов
/ 21 октября 2010

У меня есть приложение, написанное на Java, которое должно найти все доступные хосты в сети.

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

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

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

Чтобы ускорить процесс (и попробовать параллелизм в действии: Брайан Гетц), я попытался использовать 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()?

1 Ответ

1 голос
/ 31 августа 2011

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

Вот код:

http://pastie.org/2460991

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

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

...