JavaRush /Java Blog /Random-TL /Coffee break #112. Paano magdeklara, magpasimula at umuli...

Coffee break #112. Paano magdeklara, magpasimula at umulit sa isang array sa Java. Paano ihinto ang isang Java thread nang hindi gumagamit ng Thread.stop()?

Nai-publish sa grupo

Paano magdeklara, magpasimula at umulit sa isang array sa Java

Pinagmulan: FreeCodeCamp Sa artikulong ito ay pag-uusapan natin ang tungkol sa mga array sa Java. Titingnan namin ang ilang halimbawa upang matulungan kang maunawaan kung ano ang array, kung paano ito idedeklara, at kung paano ito gamitin sa Java code. Coffee break #112.  Paano magdeklara, magpasimula at umulit sa isang array sa Java.  Paano ihinto ang isang Java thread nang hindi gumagamit ng Thread.stop()?  - 1

Ano ang array?

Sa Java, gumagamit kami ng array para mag-imbak ng maraming value ng parehong uri ng data sa iisang variable. Maaari din itong isipin bilang isang koleksyon ng mga halaga ng parehong uri ng data. Nangangahulugan ito na kung mag-iimbak ka ng mga string sa iyong array, halimbawa, kung gayon ang lahat ng mga halaga sa iyong array ay dapat na mga string.

Paano magpahayag ng isang array sa Java

Gumagamit kami ng mga square bracket [ ] para magdeklara ng array . Tulad niyan:
String[] names;
Dito nagdeklara kami ng isang variable na tinatawag na mga pangalan na magtataglay ng isang hanay ng mga string. Kung kailangan nating magdeklara ng variable para sa mga integer (mga integer), gagawin natin ito tulad nito:
int[] myIntegers;
Kaya, upang lumikha ng isang array, tinutukoy namin ang uri ng data na maiimbak sa array, na sinusundan ng mga square bracket at pagkatapos ay ang pangalan ng array.

Paano simulan ang isang array sa Java

Upang simulan ang isang array ay nangangahulugan na magtalaga ng mga halaga sa array. Simulan natin ang mga array na idineklara natin sa nakaraang seksyon:
String[] names = {"John", "Jade", "Love", "Allen"};
int[] myIntegers = {10, 11, 12};
Sinimulan namin ang aming mga array sa pamamagitan ng pagpasa ng mga halaga ng parehong uri ng data, na naghihiwalay sa bawat halaga gamit ang kuwit. Kung gusto naming i-access ang mga elemento/halaga sa aming array, maa-access namin ang kanilang index number sa array. Ang index ng unang elemento ay 0. Narito ang isang halimbawa:
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
Ngayong alam na natin kung paano i-access ang bawat elemento, baguhin natin ang halaga ng ikatlong elemento.
String[] names = {"John", "Jade", "Love", "Allen"};
names[2] = "Victor";

System.out.println(names[2]);
// Victor
Maaari din nating suriin ang haba ng isang array gamit ang length property . Narito ang isang halimbawa:
String[] names = {"John", "Jade", "Love", "Allen"};
System.out.println(names.length);
// 4

Paano umulit sa pamamagitan ng isang array sa Java

Maaari tayong gumamit ng for loop para umulit sa mga elemento ng isang array .
String[] names = {"John", "Jade", "Love", "Allen"};
for (int i = 0; i < names.length; i++) {
  System.out.println(names[i]);
}

// John
// Jade
// Love
// Allen
Ang loop sa itaas ay magpi-print ng mga elemento ng aming array. Ginamit namin ang pag-aari ng haba upang tukuyin kung gaano karaming beses dapat tumakbo ang loop.

Konklusyon

Sa artikulong ito, natutunan namin kung paano magdeklara at magpasimula ng mga array sa Java code. Nakita rin namin kung paano i-access ang bawat elemento ng isang array at kung paano i-loop ang mga elementong iyon. Maligayang coding!

Paano ihinto ang isang Java thread nang hindi gumagamit ng Thread.stop()?

Source: 4comprehension Kung binabasa mo ito, malamang na nagtataka ka kung bakit, at higit sa lahat, kung paano ihinto ang isang thread kung hindi ka na lang umasa sa Thread#stop() na pamamaraan, na hindi na ginagamit mula noong Java 1.2 ? Coffee break #112.  Paano magdeklara, magpasimula at umulit sa isang array sa Java.  Paano ihinto ang isang Java thread nang hindi gumagamit ng Thread.stop()?  - 2Ang maikling sagot ay dapat kang gumamit ng mga pagkaantala dahil hindi ligtas ang Thread#stop . Ngunit kung gusto mong maunawaan kung bakit, paano, at para saan ang nakakatakot na InterruptedException na iyon , ipagpatuloy ang pagbabasa.

Problema sa Thread#stop()

Gaano man ito ka-intuitive, ang pag-interrupt sa isang tumatakbo nang thread, pagsisimula at paghinto ay dalawang magkaibang kaso. Bakit? Kapag nagsimula kami ng bagong thread, nagsisimula kami mula sa simula, na isang mahusay na tinukoy na estado, ngunit kapag sinubukan naming ihinto ang isang umiiral na thread, maaaring mangyari ito sa gitna ng isang operasyon na hindi maaantala kaagad . Isipin ang isang thread na gumagawa ng mga pagbabago sa isang istraktura ng data na ligtas sa thread. Habang ito ay nasa gitna ng kritikal na seksyon... at pagkatapos ay ang thread magically mawala - ang mga kandado ay inilabas, at ngayon isa pang thread ay maaaring obserbahan ang data istraktura naiwan sa isang hindi pantay-pantay na estado. Isaalang-alang ang sumusunod na halimbawa ng isang thread-safe na counter na may ilang panloob na estado:
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;
    }
}
Tulad ng nakikita mo, ang getAndIncrement() na pamamaraan ay dinadagdagan ang counter at binabago ang dirty flag . Tinitiyak ng mga lock na sa tuwing papasok ang isang thread sa getAndIncrement() ang dirty flag ay nakatakda sa false . Ngayon gumawa tayo ng thread at bigla itong itigil:
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
Ngayon ang threadSafeCounter instance , sa kabila ng wastong pagpapatupad, ay permanenteng nasira dahil sa biglaang paghinto ng thread. Paano ito ayusin?

Pagkagambala sa Thread ng Kooperatiba

Sa halip na itigil ang thread, dapat tayong umasa sa cooperative thread interruption. Sa madaling salita, dapat nating hilingin sa thread na ihinto ang sarili nito sa tamang sandali gamit ang Thread#interrupt . Gayunpaman, hindi sapat ang pagtawag sa Thread#interrupt sa halip na Thread#stop . Ang ligtas na pagwawakas ng isang thread ay maaari lamang makamit sa pamamagitan ng paggamit ng nakabahaging thread interrupt, na nangangahulugang sa loob ng thread kailangan nating pangasiwaan ang mga signal ng interrupt, na may dalawang uri:
  • Boolean naputol na flag

  • InterruptedException

Maaabala na Paghawak ng Flag

Habang nasa loob ng isang thread, maaari nating suriin kung naantala ito sa pamamagitan ng pagtawag sa isa sa mga pamamaraan:
Thread.currentThread().isInterrupted(); // reads the interrupted flag
Thread.interrupted(); // reads and resets the interrupted flag
Dahil walang unibersal na paraan upang mahawakan ang isang interrupt, kailangan nating maglapat ng aksyon na nababagay sa ating konteksto. Sa halimbawa mula sa nakaraang seksyon, dinadagdagan ng thread ang aming counter sa isang walang katapusang loop. Sa halip na huminto kaagad, maaari nating hintayin na makumpleto ng thread ang pataas na gawain nito at pagkatapos ay lumabas sa loop:
var threadSafeCounter = new ThreadSafeCounter();

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

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

threadSafeCounter.incrementAndGet();
Ngayon ang thread ay ligtas na natapos sa tamang oras nang hindi nagdudulot ng kaguluhan.

Pangangasiwa sa InterruptedException

Ano ang mangyayari kung susubukan naming matakpan ang naghihintay na thread? Naturally, hindi namin maaaring isaalang-alang ang interruption flag dahil abala ang thread sa isang blocking operation. Iyon ang dahilan kung bakit umiiral ang InterruptedException . Ito ay hindi isang karaniwang exception, ngunit isang iba't ibang anyo ng interrupt signal na umiiral lamang upang mahawakan ang pag-block ng mga interrupt! Tulad ng Thread#interrupted , nire-reset nito ang interruption flag . Baguhin nating muli ang halimbawa sa itaas at ipakilala ang mga paghinto bago ang bawat pagtaas. Ngayon kailangan nating hawakan ang InterruptedException na itinapon ng 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);
Sa aming kaso, sapat na upang lumabas lamang sa loop. Ngunit paano kung hindi mo iniisip na ang isang partikular na paraan ay dapat na responsable para sa paghawak ng mga pagkagambala? paano kung hindi na mababago ang method signature? Sa kasong ito, kailangan naming ibalik ang flag ng pagkaantala at/o i-repackage ang exception, halimbawa:
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    throw new RuntimeException(e);
}

Konklusyon:

  • Ang thread#stop ay hindi pinahinto nang walang dahilan - ito ay talagang napaka-insecure.

  • Ang mga thread ay huminto sa pamamagitan ng mga pagkaantala - mga signal na binibigyang-kahulugan ng thread mismo.

  • Ang InterruptedException ay hindi isang ordinaryong exception - ito ay ang built-in na paraan ng Java ng pagbibigay ng senyas na ang isang thread ay naantala.

  • Ang Thread.currentThread().isInterrupted() at Thread.interrupted() ay hindi pareho. Binabasa lang ng una ang flag ng pagkaantala , at nire-reset ito ng isa pagkatapos.

  • Walang unibersal na paraan upang mahawakan ang mga interrupt na signal - "depende ito sa mga pangyayari."

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