JavaRush /Java Blog /Random-ID /Rehat kopi #112. Cara mendeklarasikan, menginisialisasi, ...

Rehat kopi #112. Cara mendeklarasikan, menginisialisasi, dan mengulangi array di Java. Bagaimana cara menghentikan thread Java tanpa menggunakan Thread.stop()?

Dipublikasikan di grup Random-ID

Cara mendeklarasikan, menginisialisasi, dan mengulangi array di Java

Sumber: FreeCodeCamp Pada artikel ini kita akan membahas tentang array di Java. Kita akan melihat beberapa contoh untuk membantu Anda memahami apa itu array, cara mendeklarasikannya, dan cara menggunakannya dalam kode Java. Rehat kopi #112.  Cara mendeklarasikan, menginisialisasi, dan mengulangi array di Java.  Bagaimana cara menghentikan thread Java tanpa menggunakan Thread.stop()?  - 1

Apa itu larik?

Di Java, kami menggunakan array untuk menyimpan beberapa nilai dari tipe data yang sama dalam satu variabel. Ini juga dapat dianggap sebagai kumpulan nilai dari tipe data yang sama. Artinya jika Anda ingin menyimpan string dalam array Anda, misalnya, maka semua nilai dalam array Anda harus berupa string.

Cara mendeklarasikan array di Java

Kami menggunakan tanda kurung siku [] untuk mendeklarasikan array . Seperti itu:
String[] names;
Di sini kita telah mendeklarasikan sebuah variabel bernama nama yang akan menampung array string. Jika kita perlu mendeklarasikan variabel bilangan bulat (integer), maka kita akan melakukannya seperti ini:
int[] myIntegers;
Jadi, untuk membuat array, kita menentukan tipe data yang akan disimpan dalam array, diikuti dengan tanda kurung siku dan kemudian nama array.

Cara menginisialisasi array di Java

Menginisialisasi array berarti memberikan nilai pada array. Mari kita inisialisasi array yang kita deklarasikan di bagian sebelumnya:
String[] names = {"John", "Jade", "Love", "Allen"};
int[] myIntegers = {10, 11, 12};
Kami menginisialisasi array kami dengan meneruskan nilai dari tipe data yang sama, memisahkan setiap nilai dengan koma. Jika kita ingin mengakses elemen/nilai dalam array kita, kita akan mengakses nomor indeksnya dalam array. Indeks elemen pertama adalah 0. Berikut contohnya:
String[] names = {"John", "Jade", "Love", "Allen"};

System.out.println(names[0]);
// John

System.out.println(names[1]);
// Jade

System.out.println(names[2]);
// Love

System.out.println(names[3]);
// Allen
Sekarang kita tahu cara mengakses tiap elemen, mari kita ubah nilai elemen ketiga.
String[] names = {"John", "Jade", "Love", "Allen"};
names[2] = "Victor";

System.out.println(names[2]);
// Victor
Kita juga dapat memeriksa panjang array menggunakan properti length . Berikut ini contohnya:
String[] names = {"John", "Jade", "Love", "Allen"};
System.out.println(names.length);
// 4

Cara melakukan iterasi melalui array di Java

Kita dapat menggunakan perulangan for untuk melakukan iterasi melalui elemen array .
String[] names = {"John", "Jade", "Love", "Allen"};
for (int i = 0; i < names.length; i++) {
  System.out.println(names[i]);
}

// John
// Jade
// Love
// Allen
Loop di atas akan mencetak elemen array kita. Kami menggunakan properti length untuk menentukan berapa kali loop harus dijalankan.

Kesimpulan

Pada artikel ini, kita mempelajari cara mendeklarasikan dan menginisialisasi array dalam kode Java. Kita juga melihat cara mengakses setiap elemen array dan cara melakukan loop melalui elemen tersebut. Selamat membuat kode!

Bagaimana cara menghentikan thread Java tanpa menggunakan Thread.stop()?

Sumber: 4comprehension Jika Anda membaca ini, Anda mungkin bertanya-tanya mengapa, dan yang paling penting, bagaimana cara menghentikan thread jika Anda tidak bisa hanya mengandalkan metode Thread#stop() , yang sudah tidak digunakan lagi sejak Java 1.2 ? Rehat kopi #112.  Cara mendeklarasikan, menginisialisasi, dan mengulangi array di Java.  Bagaimana cara menghentikan thread Java tanpa menggunakan Thread.stop()?  - 2Jawaban singkatnya adalah Anda harus menggunakan interupsi karena Thread#stop tidak aman. Namun jika Anda ingin memahami mengapa, bagaimana, dan untuk apa InterruptedException yang mengganggu itu , teruslah membaca.

Masalah dengan Thread#stop()

Tidak peduli seberapa intuitif kedengarannya, menginterupsi thread yang sudah berjalan, memulai dan menghentikan adalah dua kasus yang sangat berbeda. Mengapa? Ketika kita memulai thread baru, kita memulai dari awal, yang merupakan keadaan yang terdefinisi dengan baik, namun ketika kita mencoba menghentikan thread yang ada, hal itu mungkin terjadi di tengah-tengah operasi yang tidak dapat segera dihentikan . Bayangkan sebuah thread membuat perubahan pada struktur data thread-safe. Saat berada di tengah-tengah bagian kritis... dan kemudian thread secara ajaib menghilang - kunci dilepaskan, dan sekarang thread lain dapat mengamati struktur data yang tertinggal dalam keadaan tidak konsisten. Perhatikan contoh penghitung thread-safe berikut dengan beberapa status internal:
class ThreadSafeCounter {

    private volatile int counter = 0;
    private volatile boolean dirty = false;

    public synchronized int incrementAndGet() {
        if (dirty) {
            throw new IllegalStateException("this should never happen");
        }
        dirty = true;
        // ...
        Thread.sleep(5000); // boilerplate not included
        // ...
        counter = counter + 1;
        dirty = false;
        return counter;
    }
}
Seperti yang Anda lihat, metode getAndIncrement() menambah penghitung dan mengubah tanda kotor . Kunci memastikan bahwa setiap kali thread memasuki getAndIncrement(), flag dirty disetel ke false . Sekarang mari kita buat thread dan hentikan secara tiba-tiba:
var threadSafeCounter = new ThreadSafeCounter();

var t1 = new Thread(() -> {
    while (true) {
        threadSafeCounter.incrementAndGet();
    }
});

t1.start();
Thread.sleep(500);
t1.stop();

threadSafeCounter.incrementAndGet();

// Exception in thread "main" java.lang.IllegalStateException: this should never happen
Sekarang instance threadSafeCounter , meskipun diterapkan dengan benar, rusak secara permanen karena thread dihentikan secara tiba-tiba. Bagaimana memperbaikinya?

Gangguan Thread Kooperatif

Daripada menghentikan thread, kita harus mengandalkan interupsi thread kooperatif. Sederhananya, kita harus meminta thread untuk berhenti sendiri pada saat yang tepat menggunakan Thread#interrupt . Namun, memanggil Thread#interrupt alih-alih Thread#stop saja tidak cukup. Pengakhiran thread yang aman hanya dapat dicapai dengan menggunakan interupsi thread bersama, yang berarti bahwa di dalam thread kita perlu menangani sinyal interupsi, yang terdiri dari dua jenis:
  • Bendera interupsi Boolean

  • Pengecualian Terganggu

Penanganan Bendera yang Dapat Diinterupsi

Saat berada di dalam thread, kita dapat memeriksa apakah thread tersebut telah terputus dengan memanggil salah satu metode:
Thread.currentThread().isInterrupted(); // reads the interrupted flag
Thread.interrupted(); // reads and resets the interrupted flag
Karena tidak ada cara universal untuk menangani interupsi, kita perlu menerapkan tindakan yang sesuai dengan konteks kita. Pada contoh di bagian sebelumnya, thread menambah penghitung kita dalam loop tak terbatas. Daripada langsung berhenti, kita cukup menunggu thread menyelesaikan pekerjaan menaiknya dan kemudian keluar dari loop:
var threadSafeCounter = new ThreadSafeCounter();

var t1 = new Thread(() -> {
    while (!Thread.interrupted()) {
        threadSafeCounter.incrementAndGet();
    }
});

t1.start();
Thread.sleep(500);
t1.interrupt();

threadSafeCounter.incrementAndGet();
Sekarang thread tersebut berakhir dengan aman pada waktu yang tepat tanpa menimbulkan kekacauan.

Menangani InterruptedException

Apa yang terjadi jika kita mencoba menghentikan thread yang menunggu? Tentu saja, kami tidak dapat memperhitungkan tanda interupsi karena thread sedang sibuk dengan operasi pemblokiran. Itu sebabnya InterruptedException ada . Ini bukan pengecualian standar, tetapi bentuk sinyal interupsi berbeda yang ada semata-mata untuk menangani interupsi pemblokiran! Seperti Thread#interrupted , ini menyetel ulang tanda interupsi . Mari kita ubah lagi contoh di atas dan berikan jeda sebelum setiap kenaikan. Sekarang kita perlu menangani InterruptedException yang dilemparkan oleh Thread#sleep :
var threadSafeCounter = new ThreadSafeCounter();

var t1 = new Thread(() -> {
    while (!Thread.interrupted()) {
        threadSafeCounter.incrementAndGet();
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            break;
        }
    }
});

t1.start();
Thread.sleep(500);
t1.interrupt();

assertThat(threadSafeCounter.incrementAndGet()).isGreaterThan(0);
Dalam kasus kami, cukup keluar dari loop saja. Namun bagaimana jika menurut Anda metode tertentu tidak bertanggung jawab menangani interupsi? bagaimana jika tanda tangan metode tidak dapat diubah? Dalam hal ini, kita perlu memulihkan tanda interupsi dan/atau mengemas ulang pengecualian, misalnya:
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    throw new RuntimeException(e);
}

Kesimpulan:

  • Thread#stop tidak ditinggalkan tanpa alasan - sebenarnya sangat tidak aman.

  • Thread dihentikan melalui interupsi - sinyal yang ditafsirkan oleh thread itu sendiri.

  • InterruptedException bukanlah pengecualian biasa - ini adalah cara bawaan Java untuk memberi sinyal bahwa suatu thread telah terputus.

  • Thread.currentThread().isInterrupted() dan Thread.interrupted() bukanlah hal yang sama. Yang pertama hanya membaca tanda interupsi , dan yang lainnya mengatur ulang setelahnya.

  • Tidak ada cara universal untuk menangani sinyal interupsi - “itu tergantung pada keadaan.”

Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION