2012-02-26 29 views
6

Próbuję jednocześnie przechodzić przez iterator Java, ale mam problemy z najlepszym sposobem, aby to zrobić.Java Iterator Concurrency

Oto, co mam, gdzie nie próbuję robić nic jednocześnie.

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

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

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

Nie powinno być żadnych warunków wyścig pomiędzy rzeczy robię na non obiektów iterator, więc nie jestem zbyt zaniepokojeni tym. Chciałbym tylko przyspieszyć, jak długo trwa przechodzenie przez iterator, nie wykonując go sekwencyjnie.

Z góry dziękuję.

Odpowiedz

4

Jednym z rozwiązań jest użycie executora do paralelizacji pracy.

Prosty przykład:

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(); 

Spowoduje to utworzenie nowego wątku dla każdego elementu w iterator, który będzie następnie wykonywać pracę. Możesz dostroić liczbę wątków za pomocą innej metody w klasie Executors lub podzielić pracę według własnego uznania (np. Inna Runnable dla każdego z wywołań metod).

5

puszkę oferują dwa możliwe podejścia:

  • pomocą puli wątków i wysyłką przedmioty otrzymane od iterator do zestawu wątków przetwarzania. Nie spowoduje to przyspieszenia samych operacji iteratora, ponieważ będą one nadal występować w jednym wątku, ale będą równoległe do rzeczywistego przetwarzania.

  • zależności od sposobu iteracja jest stworzony, może być w stanie podzielić proces iteracji do wielu segmentów, każdy być przetwarzane za pomocą oddzielnego wątku przez innego Iterator obiektu. Na przykład spójrz na metody List.sublist(int fromIndex, int toIndex) i List.listIterator(int index).

    Pozwoliłoby to na równoległe operacje iteracyjne, ale nie zawsze możliwe jest segmentowanie iteracji w ten sposób, zwykle z powodu prostego faktu, że elementy, które mają zostać powtórzone, nie są natychmiast dostępne.

  • Jako sztuczka dodatkowa, jeśli operacje iteracji są kosztowne lub powolne, takie jak te wymagane do uzyskania dostępu do bazy danych, można zauważyć poprawę przepustowości, jeśli zostaną rozdzielone na osobny wątek, który będzie używał iteratora do wypełnienia w BlockingQueue. Wątek rozsyłający będzie wtedy musiał uzyskać dostęp tylko do kolejki, bez czekania na obiekt iteratora, aby pobrać następny element.

Najważniejsza rada w tym przypadku jest to: „Użyj profilera”, zazwyczaj stosowane przez „Nie zoptymalizować przedwcześnie”. Korzystając z profilera, takiego jak VisualVM, powinieneś być w stanie ustalić dokładną przyczynę problemów z wydajnością, bez wykonywania zdjęć w ciemności.

1

Jeśli używasz Java 7, możesz użyć nowego fork/join; patrz tutorial.

Nie tylko automatycznie dzieli zadania między wątki, ale jeśli niektóre wątki kończą swoje zadania wcześniej niż inne wątki, "kradnie" niektóre zadania z innych wątków.