2015-08-02 32 views
22

Napisałem kod przy użyciu strumieni w języku java 8 i strumieni równoległych dla tej samej funkcjonalności z niestandardowym kolektorem, aby wykonać funkcję agregacji. Gdy widzę użycie procesora przy użyciu htop, pokazuje on wszystkie rdzenie procesora używane zarówno w wersji "strumieni", jak i "strumieni równoległych". Wydaje się więc, że gdy używa się list.stream(), to również wykorzystuje wszystkie procesory. Tutaj, jaka jest dokładna różnica między parallelStream() i stream() w zakresie wykorzystanie wielordzeniowych.Różnica między strumieniami w języku Java 8 i strumieniami równoległymi

+5

Strumienie nierównoległe używają tylko jednego wątku do przetworzenia ich potoku. To trudny fakt. Jeśli nie wykonasz jakiegoś jawnego wielowątkowości przy przetwarzaniu strumienia, wtedy każda dana operacja terminalu będzie wykonywana na pojedynczym rdzeniu naraz. Jeśli odwołujesz się do faktu, że htop pokazuje _some_ wykorzystanie wszystkich rdzeni, może to wynikać z tego samego wątku migrującego z rdzenia na rdzeń (nie jest przypięty do pojedynczego rdzenia). –

+2

Byłoby lepiej, gdybyś podał kod swojego programu, abyśmy mogli odtworzyć twój efekt. Jak powiedział Marko, 'list.stream()' działa sekwencyjnie w tym samym wątku, w którym wydano operację terminalową, jest to 100% faktów. Nie możemy jednak wyjaśnić, dlaczego zaobserwowałeś całe wykorzystanie procesora, ponieważ nie widzimy Twojego kodu. –

+0

Proszę znaleźć kod tutaj - https://github.com/yogirjoshi/monitortools/blob/master/src/main/java/rithm/driver/Hypothesis2.java –

Odpowiedz

30

Rozważmy następujący program:

import java.util.ArrayList; 
import java.util.List; 

public class Foo { 
    public static void main(String... args) { 
     List<Integer> list = new ArrayList<>(); 
     for (int i = 0; i < 1000; i++) { 
      list.add(i); 
     } 
     list.stream().forEach(System.out::println); 
    } 
} 

można zauważyć, że ten program wyświetli liczby od 0 do 999 sekwencyjnie, w kolejności, w jakiej znajdują się na liście. Jeśli zmienimy stream() na parallelStream(), to już nie jest tak (przynajmniej na moim komputerze): wszystkie liczby są zapisywane, ale w innej kolejności. Tak więc, widocznie, parallelStream() rzeczywiście używa wielu wątków.

Model htop został wyjaśniony faktem, że nawet aplikacje jednowątkowe są dzielone na różne rdzenie przez większość współczesnych systemów operacyjnych (części tego samego wątku mogą działać na kilku rdzeniach, ale oczywiście nie w tym samym czasie). Jeśli widzisz, że proces używał więcej niż jednego rdzenia, nie oznacza to koniecznie, że program używa wielu wątków.

Także wydajność może nie ulec poprawie w przypadku korzystania z wielu wątków. Koszt synchronizacji może zniszczyć zyski z używania wielu wątków. W przypadku prostych scenariuszy testowych często tak jest. Na przykład w powyższym przykładzie System.out jest zsynchronizowany. Tak więc, efektywnie, tylko liczba może być zapisana w tym samym czasie, chociaż używa się wielu wątków.

Powiązane problemy