JavaRush /Blog Java /Random-MS /Coffee break #112. Bagaimana untuk mengisytiharkan, memul...

Coffee break #112. Bagaimana untuk mengisytiharkan, memulakan dan mengulangi tatasusunan dalam Java. Bagaimana untuk menghentikan benang Java tanpa menggunakan Thread.stop()?

Diterbitkan dalam kumpulan

Bagaimana untuk mengisytiharkan, memulakan dan mengulangi tatasusunan dalam Java

Sumber: FreeCodeCamp Dalam artikel ini kita akan bercakap tentang tatasusunan dalam Java. Kami akan melihat beberapa contoh untuk membantu anda memahami apa itu tatasusunan, cara mengisytiharkannya dan cara menggunakannya dalam kod Java. Coffee break #112.  Bagaimana untuk mengisytiharkan, memulakan dan mengulangi tatasusunan dalam Java.  Bagaimana untuk menghentikan benang Java tanpa menggunakan Thread.stop()?  - 1

Apakah tatasusunan?

Di Java, kami menggunakan tatasusunan untuk menyimpan berbilang nilai jenis data yang sama dalam satu pembolehubah. Ia juga boleh dianggap sebagai koleksi nilai jenis data yang sama. Ini bermakna jika anda akan menyimpan rentetan dalam tatasusunan anda, contohnya, maka semua nilai dalam tatasusunan anda mestilah rentetan.

Bagaimana untuk mengisytiharkan tatasusunan dalam Java

Kami menggunakan kurungan segi empat sama [ ] untuk mengisytiharkan tatasusunan . Macam itu:
String[] names;
Di sini kami telah mengisytiharkan pembolehubah yang dipanggil nama yang akan memegang tatasusunan rentetan. Jika kita perlu mengisytiharkan pembolehubah untuk integer (integer), maka kita akan melakukannya seperti ini:
int[] myIntegers;
Jadi, untuk mencipta tatasusunan, kami menentukan jenis data yang akan disimpan dalam tatasusunan, diikuti dengan kurungan segi empat sama dan kemudian nama tatasusunan.

Bagaimana untuk memulakan tatasusunan dalam Java

Untuk memulakan tatasusunan bermakna memberikan nilai kepada tatasusunan. Mari kita mulakan tatasusunan yang kita isytiharkan dalam bahagian sebelumnya:
String[] names = {"John", "Jade", "Love", "Allen"};
int[] myIntegers = {10, 11, 12};
Kami memulakan tatasusunan kami dengan menghantar nilai jenis data yang sama, memisahkan setiap nilai dengan koma. Jika kami ingin mengakses elemen/nilai dalam tatasusunan kami, kami akan mengakses nombor indeksnya dalam tatasusunan. Indeks bagi elemen pertama ialah 0. Berikut ialah contoh:
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 setelah kita tahu cara mengakses setiap elemen, mari tukar nilai elemen ketiga.
String[] names = {"John", "Jade", "Love", "Allen"};
names[2] = "Victor";

System.out.println(names[2]);
// Victor
Kita juga boleh menyemak panjang tatasusunan menggunakan sifat panjang . Berikut ialah contoh:
String[] names = {"John", "Jade", "Love", "Allen"};
System.out.println(names.length);
// 4

Bagaimana untuk lelaran melalui tatasusunan dalam Java

Kita boleh menggunakan gelung for untuk melelaran melalui elemen tatasusunan .
String[] names = {"John", "Jade", "Love", "Allen"};
for (int i = 0; i < names.length; i++) {
  System.out.println(names[i]);
}

// John
// Jade
// Love
// Allen
Gelung di atas akan mencetak elemen tatasusunan kami. Kami menggunakan sifat panjang untuk menentukan berapa kali gelung harus dijalankan.

Kesimpulan

Dalam artikel ini, kami mempelajari cara mengisytiharkan dan memulakan tatasusunan dalam kod Java. Kami juga melihat cara untuk mengakses setiap elemen tatasusunan dan cara mengulung elemen tersebut. Selamat mengekod!

Bagaimana untuk menghentikan benang Java tanpa menggunakan Thread.stop()?

Sumber: 4comprehension Jika anda membaca ini, maka anda mungkin tertanya-tanya mengapa, dan yang paling penting, bagaimana untuk menghentikan utas jika anda tidak boleh bergantung pada kaedah Thread#stop() sahaja , yang telah ditamatkan sejak Java 1.2 ? Coffee break #112.  Bagaimana untuk mengisytiharkan, memulakan dan mengulangi tatasusunan dalam Java.  Bagaimana untuk menghentikan benang Java tanpa menggunakan Thread.stop()?  - 2Jawapan ringkasnya ialah anda harus menggunakan gangguan kerana Thread#stop tidak selamat. Tetapi jika anda ingin memahami mengapa, bagaimana, dan untuk apa InterruptedException yang menjengkelkan itu , teruskan membaca.

Masalah dengan Thread#stop()

Tidak kira betapa intuitifnya bunyinya, mengganggu utas yang sudah berjalan, memulakan dan berhenti adalah dua kes yang sama sekali berbeza. kenapa? Apabila kami memulakan utas baharu, kami bermula dari awal, iaitu keadaan yang jelas, tetapi apabila kami cuba menghentikan utas sedia ada, ini mungkin berlaku di tengah-tengah operasi yang tidak boleh diganggu serta-merta . Bayangkan benang membuat perubahan pada struktur data selamat benang. Semasa ia berada di tengah-tengah bahagian kritikal... dan kemudian benang itu hilang secara ajaib - kunci dilepaskan, dan kini benang lain boleh memerhatikan struktur data yang ditinggalkan dalam keadaan tidak konsisten. Pertimbangkan contoh berikut bagi kaunter selamat benang dengan beberapa keadaan dalaman:
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, kaedah getAndIncrement() menambah pembilang dan menukar bendera dirty . Kunci memastikan bahawa setiap kali benang memasuki getAndIncrement() bendera dirty ditetapkan kepada false . Sekarang mari kita buat benang dan hentikannya 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 , walaupun dilaksanakan dengan betul, rosak secara kekal kerana urutan dihentikan secara tiba-tiba. Bagaimana untuk membetulkannya?

Gangguan Benang Koperasi

Daripada menghentikan benang, kita harus bergantung pada gangguan benang koperasi. Ringkasnya, kita mesti meminta utas untuk berhenti sendiri pada masa yang betul menggunakan Thread#interrupt . Walau bagaimanapun, memanggil Thread#interrupt dan bukannya Thread#stop tidak mencukupi. Penamatan benang yang selamat hanya boleh dicapai dengan menggunakan sampukan benang yang dikongsi, yang bermaksud bahawa dalam rangkaian itu kita perlu mengendalikan isyarat sampukan, yang terdapat dalam dua jenis:
  • Bendera terputus Boolean

  • InterruptedException

Pengendalian Bendera Boleh Terganggu

Semasa berada di dalam benang, kita boleh menyemak sama ada ia telah diganggu dengan memanggil salah satu kaedah:
Thread.currentThread().isInterrupted(); // reads the interrupted flag
Thread.interrupted(); // reads and resets the interrupted flag
Memandangkan tiada cara universal untuk mengendalikan gangguan, kita perlu menggunakan tindakan yang sesuai dengan konteks kita. Dalam contoh dari bahagian sebelumnya, benang menambah kaunter kami dalam gelung tak terhingga. Daripada berhenti serta-merta, kita hanya boleh menunggu benang menyelesaikan kerja menaiknya dan kemudian keluar dari gelung:
var threadSafeCounter = new ThreadSafeCounter();

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

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

threadSafeCounter.incrementAndGet();
Kini benang ditamatkan dengan selamat pada masa yang sesuai tanpa menyebabkan huru-hara.

Mengendalikan InterruptedException

Apa yang berlaku jika kita cuba mengganggu urutan yang menunggu? Sememangnya, kita tidak boleh mengambil kira bendera gangguan kerana benang sibuk dengan operasi menyekat. Itulah sebabnya InterruptedException wujud . Ini bukan pengecualian standard, tetapi bentuk isyarat gangguan yang berbeza yang wujud semata-mata untuk mengendalikan gangguan menyekat! Seperti Thread#interrupted , ia menetapkan semula bendera gangguan . Mari tukar contoh di atas sekali lagi dan perkenalkan jeda sebelum setiap kenaikan. Sekarang kita perlu mengendalikan 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 kes kami, cukup untuk keluar dari gelung. Tetapi bagaimana jika anda tidak berpendapat bahawa kaedah tertentu harus bertanggungjawab untuk mengendalikan gangguan? bagaimana jika tandatangan kaedah tidak boleh diubah? Dalam kes ini, kita perlu memulihkan bendera gangguan dan/atau membungkus semula pengecualian, sebagai contoh:
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 ditamatkan tanpa sebab - ia sebenarnya sangat tidak selamat.

  • Benang dihentikan melalui gangguan - isyarat yang ditafsirkan oleh benang itu sendiri.

  • InterruptedException bukan pengecualian biasa - ia adalah cara terbina dalam Java untuk memberi isyarat bahawa benang telah diganggu.

  • Thread.currentThread().isInterrupted() dan Thread.interrupted() bukanlah perkara yang sama. Yang pertama hanya membaca bendera gangguan , dan yang lain menetapkannya semula selepas itu.

  • Tiada cara universal untuk mengendalikan isyarat gangguan - "ia bergantung pada keadaan."

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