0Pricing
Java Academy · Pelajaran

Keamanan Thread dan Efek Samping

Hindari keadaan mutable yang dibagikan.

Keamanan Thread dan Efek Samping adalah pelajaran Java Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Java Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Java Academy mencakup 4 pelajaran total.

Paralel Berarti Akses Bersamaan

Dalam aliran parallel, beberapa utas menjalankan lambda Anda pada waktu yang sama. Setiap status bersama yang dapat diubah yang disentuhnya menjadi kondisi balapan.

import java.util.stream.IntStream;

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

Bahaya Mengubah Variabel Bersama

Penghitung biasa yang disentuh oleh banyak utas dapat kehilangan pembaruan. Jangan pernah mengakumulasi hasil ke dalam status bersama yang dapat diubah di dalam forEach.

import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        AtomicInteger counter = new AtomicInteger();
        IntStream.rangeClosed(1, 1000).parallel()
            .forEach(n -> counter.incrementAndGet());
        System.out.println(counter.get());
    }
}

Mengapa Koleksi Biasa Rusak

Menambahkan elemen ke ArrayList yang tidak aman untuk utas dari forEach parallel dapat merusaknya atau menghilangkan elemen. Solusinya adalah tidak berbagi dan mengubahnya sama sekali.

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

public class Main {
    public static void main(String[] args) {
        List<Integer> result = IntStream.rangeClosed(1, 10).parallel()
            .boxed()
            .collect(Collectors.toList());
        System.out.println(result.size());
    }
}

Alat yang Tepat: collect

Gunakan collect, bukan forEach yang menghasilkan efek samping. Kerangka kolektor mengakumulasi wadah parsial dengan aman untuk setiap utas, lalu menggabungkannya.

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

public class Main {
    public static void main(String[] args) {
        List<Integer> squares = IntStream.rangeClosed(1, 6).parallel()
            .map(n -> n * n)
            .boxed()
            .collect(Collectors.toList());
        System.out.println(squares);
    }
}

Alat yang Tepat: reduce

reduce pada dasarnya aman untuk utas jika operasinya asosiatif dan tidak memiliki status, karena operasi tersebut menggabungkan hasil parsial tanpa perubahan bersama.

import java.util.stream.IntStream;

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

Lambda Tanpa Status

Lambda dalam aliran harus tanpa status: hasilnya hanya bergantung pada masukan, bukan pada variabel eksternal yang dapat diubah atau elemen sebelumnya.

import java.util.stream.IntStream;

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

Tipe Atomik sebagai Jalan Keluar

Jika Anda benar-benar harus berbagi penghitung, gunakan kelas atomik seperti AtomicLong. Kelas tersebut menyerialkan pembaruan dengan benar, meskipun menambah persaingan akses.

import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        AtomicLong sum = new AtomicLong();
        IntStream.rangeClosed(1, 1000).parallel()
            .forEach(sum::addAndGet);
        System.out.println(sum.get());
    }
}

Koleksi Bersamaan

Jika Anda memerlukan map bersama di antara utas, ConcurrentHashMap aman digunakan. Namun, jika memungkinkan, tetap utamakan Collectors.groupingByConcurrent.

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

public class Main {
    public static void main(String[] args) {
        List<String> words = List.of("a", "bb", "cc", "ddd");
        Map<Integer, List<String>> byLen = words.parallelStream()
            .collect(Collectors.groupingByConcurrent(String::length));
        System.out.println(byLen);
    }
}

Hindari Logika yang Bergantung pada Urutan

Jangan bergantung pada urutan kemunculan di dalam lambda parallel. Operasi yang mengasumsikan pemrosesan berurutan akan menghasilkan hasil yang salah secara parallel.

import java.util.stream.IntStream;

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

Fungsi Murni Dapat Diparalelkan dengan Aman

Aturan utamanya: tulislah operasi yang murni, tanpa status, dan tidak saling mengganggu. Dengan demikian, aliran dapat berupa sequential atau parallel dan tetap menghasilkan hasil yang identik serta benar.

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

public class Main {
    public static void main(String[] args) {
        List<String> in = List.of("red", "green", "blue");
        String out = in.parallelStream()
            .map(String::toUpperCase)
            .sorted()
            .collect(Collectors.joining(","));
        System.out.println(out);
    }
}

Tidak Saling Mengganggu

Jangan mengubah koleksi sumber saat aliran sedang melintasinya. Hal ini menyebabkan ConcurrentModificationException atau perilaku tak terdefinisi, baik secara sequential maupun parallel.

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

public class Main {
    public static void main(String[] args) {
        List<Integer> src = List.of(1, 2, 3, 4);
        List<Integer> doubled = src.parallelStream()
            .map(n -> n * 2)
            .collect(Collectors.toList());
        System.out.println(doubled);
    }
}

Pemeriksaan Singkat

Apa cara yang disarankan untuk mengakumulasi hasil dari aliran parallel?

Rangkuman

Anda telah menjaga aliran parallel tetap benar:

  • Status bersama yang dapat diubah dalam lambda parallel menyebabkan kondisi balapan.
  • Utamakan collect dan reduce daripada forEach yang menghasilkan efek samping.
  • Jaga agar lambda tidak memiliki status, murni, dan tidak saling mengganggu.
  • Jika harus berbagi, gunakan tipe atomik atau koleksi bersamaan, tetapi jadikan itu pilihan terakhir.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Keamanan Thread dan Efek Samping” gratis?

Ya — teks lengkap “Keamanan Thread dan Efek Samping” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Java Academy, upgrade ke CoddyKit PRO. Kursus Java Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Keamanan Thread dan Efek Samping”?

Hindari keadaan mutable yang dibagikan. Kamu berlatih Java Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Java Academy?

Tidak diperlukan pengalaman sebelumnya. Java Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “Keamanan Thread dan Efek Samping” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Java Academy ini?

Ya. Setiap pelajaran Java Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Membuat Stream Paralel
  2. Kapan Paralelisme Membantu
  3. Keamanan Thread dan Efek Samping
  4. Kesalahan Umum
← Kembali ke Java Academy