0Pricing
Java Academy · Lekcja

Tworzenie strumieni równoległych

parallel() i parallelStream()

Tworzenie strumieni równoległych to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.

Działanie strumieni równoległych

Strumień równoległy dzieli dane na części, przetwarza je na wielu wątkach, a następnie łączy wyniki. Celem jest zwiększenie przepustowości w przypadku dużych obciążeń.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int sum = IntStream.rangeClosed(1, 1000)
            .parallel()
            .sum();
        System.out.println(sum);
    }
}

parallel() na istniejącym strumieniu

Wywołanie parallel() przekształca strumień sekwencyjny w równoległy. Może znajdować się w dowolnym miejscu potoku.

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> nums = List.of(1, 2, 3, 4, 5);
        int total = nums.stream()
            .parallel()
            .mapToInt(Integer::intValue)
            .sum();
        System.out.println(total);
    }
}

parallelStream() dla kolekcji

Collection.parallelStream() bezpośrednio tworzy strumień równoległy, stanowiąc skrót zamiast stream().parallel().

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> words = List.of("a", "bb", "ccc");
        int chars = words.parallelStream()
            .mapToInt(String::length)
            .sum();
        System.out.println(chars);
    }
}

Powrót do trybu sekwencyjnego

sequential() przywraca wykonywanie jednowątkowe. O trybie całego potoku decyduje ostatnie wywołanie parallel() lub sequential().

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int sum = IntStream.rangeClosed(1, 100)
            .parallel()
            .sequential()
            .sum();
        System.out.println(sum);
    }
}

Sprawdzanie isParallel

isParallel() informuje, czy strumień będzie wykonywany równolegle.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        System.out.println(IntStream.range(0, 10).isParallel());
        System.out.println(IntStream.range(0, 10).parallel().isParallel());
    }
}

Ten sam wynik, inne wykonanie

W przypadku operacji asocjacyjnych, takich jak sumowanie, strumienie równoległe i sekwencyjne zwracają ten sam wynik. Różni się tylko strategia wykonania.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int seq = IntStream.rangeClosed(1, 50).sum();
        int par = IntStream.rangeClosed(1, 50).parallel().sum();
        System.out.println(seq == par);
    }
}

Wspólna pula ForkJoinPool

Strumienie równoległe korzystają ze współdzielonej puli ForkJoinPool.commonPool(). Jej domyślny rozmiar jest równy liczbie dostępnych procesorów pomniejszonej o jeden.

public class Main {
    public static void main(String[] args) {
        System.out.println(Runtime.getRuntime().availableProcessors());
    }
}

Kolejność wątków nie jest gwarantowana

W przypadku forEach strumienie równoległe mogą wypisywać elementy w dowolnej kolejności, ponieważ poszczególne części kończą działanie w różnym czasie. Jeśli kolejność ma znaczenie, należy użyć forEachOrdered.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        IntStream.rangeClosed(1, 5)
            .parallel()
            .forEachOrdered(System.out::println);
    }
}

Redukcja łączy częściowe wyniki

Wewnętrznie redukcja równoległa oblicza częściowe wyniki dla poszczególnych części i łączy je za pomocą funkcji łączącej. Aby wynik był poprawny, operacja musi być asocjacyjna.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int product = IntStream.rangeClosed(1, 6)
            .parallel()
            .reduce(1, (a, b) -> a * b);
        System.out.println(product);
    }
}

Zbieranie równoległe

Mechanizm kolektorów obsługuje zbieranie równoległe przez łączenie częściowych kontenerów. groupingBy działa poprawnie równolegle.

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> words = List.of("apple", "banana", "avocado", "cherry");
        Map<Character, List<String>> byFirst = words.parallelStream()
            .collect(Collectors.groupingBy(w -> w.charAt(0)));
        System.out.println(byFirst);
    }
}

Nie każdy strumień działa szybciej

Włączenie równoległości jest proste, ale nie zawsze przynosi korzyści. W przypadku małych zbiorów danych lub tanich operacji wykonanie równoległe może być wolniejsze z powodu narzutu dzielenia i scalania.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        long count = IntStream.rangeClosed(1, 10)
            .parallel()
            .filter(n -> n % 2 == 0)
            .count();
        System.out.println(count);
    }
}

Szybkie sprawdzenie

Jaka pula wątków domyślnie wykonuje strumienie równoległe?

Podsumowanie

Utworzono strumienie równoległe:

  • parallel() przekształca dowolny strumień, a parallelStream() jest skrótem dla kolekcji.
  • sequential() przywraca tryb sekwencyjny; decyduje ostatnie wywołanie.
  • Strumienie te działają we współdzielonej puli ForkJoinPool.commonPool().
  • Wyniki operacji asocjacyjnych są takie same jak w trybie sekwencyjnym, ale kolejność i szybkość nie są gwarantowane.

Często zadawane pytania

Czy lekcja „Tworzenie strumieni równoległych” jest bezpłatna?

Tak — pełny tekst „Tworzenie strumieni równoległych” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Tworzenie strumieni równoległych”?

parallel() i parallelStream() Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Java Academy?

Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Tworzenie strumieni równoległych”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?

Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Tworzenie strumieni równoległych
  2. Kiedy równoległość pomaga
  3. Bezpieczeństwo wątkowe i efekty uboczne
  4. Typowe pułapki
← Powrót do Java Academy