Java Academy · Oppitunti

Rinnakkaisvirtojen luonti

parallel() ja parallelStream().

Oppitunti 1/413 vaihetta

Rinnakkaisvirtojen luonti on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.

Mitä rinnakkaiset virrat tekevät

Rinnakkainen virta jakaa datansa osiin, käsittelee osat useissa säikeissä ja yhdistää sitten tulokset. Tavoitteena on suurempi suorituskyky suurilla työmäärillä.

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() olemassa olevalle virralle

parallel()-kutsulla peräkkäinen virta muutetaan rinnakkaiseksi. Kutsu voi esiintyä missä tahansa putkistossa.

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

Collection.parallelStream() luo rinnakkaisen virran suoraan. Se on lyhyt muoto yhdistelmälle 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);
    }
}

Takaisin peräkkäiseen suoritukseen

sequential() palauttaa virran yksisäikeiseen suoritukseen. Viimeinen koko putkistossa kutsuttu parallel()- tai sequential()-operaatio määrittää suoritustavan.

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

isParallel-tilan tarkistaminen

isParallel() ilmoittaa, suoritetaanko virta rinnakkain.

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

Sama tulos, erilainen suoritus

Assosiatiiviset operaatiot, kuten summaus, tuottavat rinnakkaisilla ja peräkkäisillä virroilla saman tuloksen. Vain suoritusstrategia eroaa.

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

Yhteinen ForkJoinPool

Rinnakkaiset virrat käyttävät jaettua ForkJoinPool.commonPool()-poolia. Sen oletuskoko on käytettävissä olevien prosessorien määrä vähennettynä yhdellä.

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

Säikeiden järjestystä ei taata

forEach-operaation kanssa rinnakkaiset virrat voivat tulostaa alkiot missä tahansa järjestyksessä, koska osat valmistuvat eri aikoina. Jos järjestyksellä on merkitystä, käyttäkää forEachOrdered-operaatiota.

import java.util.stream.IntStream;

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

Redusointi yhdistää osatulokset

Rinnakkainen redusointi laskee konepellin alla osatulokset kullekin osalle ja yhdistää ne yhdistelyfunktiolla. Operaation on oltava assosiatiivinen, jotta tulos on oikea.

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

Kerääminen rinnakkain

Kerääjäkehys tukee rinnakkaista keräämistä yhdistämällä osittaiset säiliöt. groupingBy toimii oikein rinnakkaisessa suorituksessa.

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

Kaikki virrat eivät nopeudu

Rinnakkaisuuden käyttöönotto on helppoa, mutta siitä ei ole aina hyötyä. Pienillä aineistoilla tai kevyillä operaatioilla rinnakkainen suoritus voi olla hitaampaa osiin jakamisen ja yhdistämisen aiheuttaman yleiskustannuksen vuoksi.

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

Pikatarkistus

Mikä säiepooli suorittaa rinnakkaiset virrat oletusarvoisesti?

Kertaus

Loitte rinnakkaisia virtoja:

  • parallel() muuttaa minkä tahansa virran rinnakkaiseksi; parallelStream() on kokoelmille tarkoitettu lyhyt muoto.
  • sequential() palauttaa peräkkäiseen suoritukseen; viimeinen kutsu määrittää suoritustavan.
  • Virrat suoritetaan jaetussa ForkJoinPool.commonPool()-poolissa.
  • Assosiatiivisten operaatioiden tulokset vastaavat peräkkäisen suorituksen tuloksia, mutta järjestystä ja nopeutta ei taata.
Aloita maksutta

Opi Java tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
104
Oppitunnit
374

Usein kysytyt kysymykset

Onko oppitunti ”Rinnakkaisvirtojen luonti” ilmainen?

Kyllä – oppitunnin ”Rinnakkaisvirtojen luonti” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Rinnakkaisvirtojen luonti”?

parallel() ja parallelStream(). Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.

Kuinka kauan ”Rinnakkaisvirtojen luonti”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?

Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Rinnakkaisvirtojen luonti
  2. Milloin rinnakkaisuus auttaa
  3. Säieturvallisuus ja sivuvaikutukset
  4. Yleiset sudenkuopat
← Takaisin: Java Academy