Java Academy · Pelajaran

Strim Selari: Prestasi dan Perangkap

Dayakan strim selari, fahami kumpulan thread umum dan elakkan pepijat keadaan boleh ubah yang dikongsi.

Pelajaran 2 daripada 413 langkah

Strim Selari: Prestasi dan Perangkap ialah pelajaran Java Academy percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Java Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Java Academy merangkumi sejumlah 4 pelajaran.

Mendayakan Strim Selari

Panggil .parallel() pada mana-mana strim atau gunakan Collection.parallelStream(). Operasi strim dijalankan dalam ForkJoinPool umum (lalai: teras CPU - 1 utas).

long count = list.parallelStream()
    .filter(n -> n % 2 == 0)
    .count();
System.out.println(count);

Bila Strim Selari Berbaloi

Strim selari berbaloi apabila: set data besar (100,000+ elemen), operasi pada setiap elemen memerlukan pengiraan yang berat, dan saluran pemprosesan tidak mempunyai keadaan serta tidak bergantung pada susunan.

// Good candidate: CPU-heavy computation on large dataset
long sum = LongStream.rangeClosed(1, 10_000_000)
    .parallel()
    .filter(n -> isPrime(n))
    .sum();
System.out.println(sum);

Bila TIDAK Menggunakan Strim Selari

Elakkan strim selari untuk: koleksi kecil, operasi yang terikat pada input/output (operasi ini menyekat utas ForkJoinPool), operasi berkeadaan (pengisihan, penyingkiran pendua), atau apabila susunan penting dan mahal untuk dipulihkan.

// Bad: I/O bound — blocking ForkJoinPool threads starves other tasks
List<String> result = urls.parallelStream()
    .map(url -> httpGet(url)) // BLOCKS the common pool
    .collect(Collectors.toList());

Pepijat Keadaan Boleh Ubah Dikongsi

Strim selari menjalankan operasi pada berbilang utas secara serentak. Mengubah suai koleksi boleh ubah yang dikongsi menyebabkan perlumbaan data dan hasil yang tidak betul.

// RACE CONDITION — never do this:
List<Integer> results = new ArrayList<>(); // not thread-safe
numbers.parallelStream().forEach(n -> results.add(n)); // corrupts list!
// Fix:
List<Integer> safe = numbers.parallelStream().collect(Collectors.toList());

Operasi Berkeadaan: sorted dan Penyingkiran Pendua

sorted() dan distinct() perlu melihat semua elemen sebelum menghasilkan output, lalu mengehadkan keselarian dan sering menjadikan pemprosesan selari lebih perlahan daripada pemprosesan berjujukan.

// sorted() forces collect-all, then sort — parallel overhead usually not worth it:
list.parallelStream().sorted().collect(Collectors.toList());

Operasi Sensitif terhadap Susunan

findFirst() dan forEachOrdered() mengekalkan susunan pertemuan dalam strim selari, lalu menambah kos penyegerakan. Gunakan findAny() atau forEach() apabila susunan tidak penting.

// Faster in parallel (order-insensitive):
Optional<Integer> any = list.parallelStream().filter(n -> n > 10).findAny();
// Slower in parallel (must preserve order):
Optional<Integer> first = list.parallelStream().filter(n -> n > 10).findFirst();

Memilih Saiz Kumpulan Utas

ForkJoinPool umum menggunakan Runtime.getRuntime().availableProcessors() - 1 utas. Jalankan strim selari pada kumpulan tersuai dengan menyerahkannya dari dalam panggilan ForkJoinPool.invoke().

ForkJoinPool custom = new ForkJoinPool(8);
long result = custom.submit(
    () -> LongStream.rangeClosed(1, 1_000_000).parallel().sum()
).get();

Mengukur Prestasi Selari Berbanding Berjujukan

Sentiasa ukur prestasi dengan JMH menggunakan saiz data yang realistik. Overhed selari (pembahagian, penyelarasan utas, penggabungan) hanya wajar apabila masa pengiraan jauh melebihi overhed tersebut.

@Benchmark
public long sequential() { return LongStream.rangeClosed(1,1_000_000).sum(); }
@Benchmark
public long parallel()   { return LongStream.rangeClosed(1,1_000_000).parallel().sum(); }

Operasi Pengurangan dengan Pemprosesan Selari

reduce() dan collect() direka untuk berfungsi dengan betul secara selari apabila operasi bersifat bersekutu dan nilai identiti adalah betul.

// Associative reduce — safe in parallel:
int sum = list.parallelStream().reduce(0, Integer::sum);
// Non-associative: subtraction — NOT safe in parallel:
int bad = list.parallelStream().reduce(0, (a, b) -> a - b); // wrong result!

Keupayaan untuk Dipecahkan Penting

Strim selari memecahkan sumber data menggunakan Spliterator. ArrayList dan tatasusunan dipecahkan dalam O(1); LinkedList dan HashSet sukar dipecahkan, lalu mengurangkan kecekapan selari.

Ringkasan: Senarai Semak Strim Selari

Sebelum menggunakan pemprosesan selari: (1) set data besar, (2) operasi terikat CPU, (3) tiada keadaan boleh ubah yang dikongsi, (4) tidak sensitif terhadap susunan, (5) sumber yang boleh dipecahkan (tatasusunan/ArrayList). Jika ragu-ragu, ukur prestasi.

Semakan Pantas

Apakah yang berlaku apabila anda menambah elemen pada koleksi yang tidak selamat untuk utas dalam strim selari menggunakan forEach?

Imbas Kembali

Strim selari menggunakan ForkJoinPool. Ia berkesan untuk saluran pemprosesan yang besar, terikat CPU, tidak sensitif terhadap susunan dan tidak mempunyai keadaan. Jangan ubah keadaan yang dikongsi. Ukur prestasi sebelum membuat keputusan — pemprosesan selari sering lebih perlahan untuk data kecil.

Percuma untuk bermula

Pelajari Java dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
104
Pelajaran
374

Soalan Lazim

Adakah pelajaran “Strim Selari: Prestasi dan Perangkap” percuma?

Ya — teks penuh “Strim Selari: Prestasi dan Perangkap” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Java Academy, tingkat taraf kepada CoddyKit PRO. Kursus Java Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Strim Selari: Prestasi dan Perangkap”?

Dayakan strim selari, fahami kumpulan thread umum dan elakkan pepijat keadaan boleh ubah yang dikongsi. Anda berlatih Java Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Java Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Java Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Strim Selari: Prestasi dan Perangkap” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Java Academy ini?

Ya. Setiap pelajaran Java Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. flatMap untuk Koleksi Bersarang
  2. Strim Selari: Prestasi dan Perangkap
  3. Spliterator: Pemisahan untuk Keselarian
  4. Strim Tanpa Had dengan iterate dan generate
← Kembali ke Java Academy