Параллелизм Java Iterator - PullRequest
       18

Параллелизм Java Iterator

6 голосов
/ 26 февраля 2012

Я пытаюсь зацикливаться на итераторе Java одновременно, но у меня возникают проблемы с лучшим способом сделать это.

Вот то, что у меня есть, когда я не пытаюсь сделать что-то одновременно.

Long l;    
Iterator<Long> i = getUserIDs();

while (i.hasNext()) {
    l = i.next();

    someObject.doSomething(l);
    anotheObject.doSomething(l);
}

Между тем, что я делаю с объектами, не являющимися итераторами, не должно быть условий гонки, поэтому я не слишком беспокоюсь об этом.Я просто хотел бы ускорить цикл обхода итератора, не выполняя его последовательно.

Заранее спасибо.

Ответы [ 3 ]

5 голосов
/ 26 февраля 2012

Одним из решений является использование исполнителя для распараллеливания вашей работы.

Простой пример:

ExecutorService executor = Executors.newCachedThreadPool();

Iterator<Long> i = getUserIDs();
while (i.hasNext()) {
    final Long l = i.next();

    Runnable task = new Runnable() {
        public void run() {
            someObject.doSomething(l);
            anotheObject.doSomething(l);
        }
    }

    executor.submit(task);
}

executor.shutdown();

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

5 голосов
/ 26 февраля 2012

А может предложить два возможных подхода:

  • Использование пула потоков и отправка элементов, полученных от итератора, в набор потоков обработки. Это не ускорит сами операции итератора, так как они все равно будут выполняться в одном потоке, но будет распараллеливать фактическую обработку.

  • В зависимости от того, как создается итерация, вы можете разделить процесс итерации на несколько сегментов, каждый из которых будет обрабатываться отдельным потоком через отдельный объект Iterator. Для примера рассмотрим методы List.sublist(int fromIndex, int toIndex) и List.listIterator(int index).

    Это позволило бы операциям итератора происходить параллельно, но не всегда возможно сегментировать итерацию подобным образом, как правило, из-за того простого факта, что элементы, подлежащие итерации, не доступны сразу.

  • В качестве бонусной уловки, если итерационные операции дороги или медленны, такие как те, которые требуются для доступа к базе данных, вы можете увидеть улучшение пропускной способности, если выделите их в отдельный поток, который будет использовать итератор для заполните BlockingQueue. Тогда потоку диспетчера нужно будет только получить доступ к очереди, не дожидаясь объекта итератора, чтобы получить следующий элемент.

Самый важный совет в этом случае заключается в следующем: «Используйте свой профилировщик» , обычно за ним следует «Не оптимизировать преждевременно» . Используя профилировщик, такой как VisualVM , вы сможете определить точную причину любых проблем с производительностью, не снимая в темноте.

1 голос
/ 26 февраля 2012

Если вы используете Java 7, вы можете использовать новый fork / join;см. учебник .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...