JavaRush /Java-Blog /Random-DE /Kaffeepause Nr. 112. So deklarieren, initialisieren und i...

Kaffeepause Nr. 112. So deklarieren, initialisieren und iterieren Sie über ein Array in Java. Wie kann ich einen Java-Thread stoppen, ohne Thread.stop() zu verwenden?

Veröffentlicht in der Gruppe Random-DE

So deklarieren, initialisieren und iterieren Sie über ein Array in Java

Quelle: FreeCodeCamp In diesem Artikel werden wir über Arrays in Java sprechen. Wir sehen uns einige Beispiele an, um Ihnen zu helfen, zu verstehen, was ein Array ist, wie man es deklariert und wie man es in Java-Code verwendet. Kaffeepause Nr. 112.  So deklarieren, initialisieren und iterieren Sie über ein Array in Java.  Wie kann ich einen Java-Thread stoppen, ohne Thread.stop() zu verwenden?  - 1

Was ist ein Array?

In Java verwenden wir ein Array, um mehrere Werte desselben Datentyps in einer einzigen Variablen zu speichern. Man kann es sich auch als eine Sammlung von Werten desselben Datentyps vorstellen. Das heißt, wenn Sie beispielsweise Zeichenfolgen in Ihrem Array speichern möchten, müssen alle Werte in Ihrem Array Zeichenfolgen sein.

So deklarieren Sie ein Array in Java

Wir verwenden eckige Klammern [] , um ein Array zu deklarieren . Ungefähr so:
String[] names;
Hier haben wir eine Variable namens „names“ deklariert, die ein Array von Zeichenfolgen enthält. Wenn wir eine Variable für ganze Zahlen (Ganzzahlen) deklarieren müssen , dann machen wir das so:
int[] myIntegers;
Um ein Array zu erstellen, geben wir also den Datentyp an, der im Array gespeichert werden soll, gefolgt von eckigen Klammern und dann dem Namen des Arrays.

So initialisieren Sie ein Array in Java

Ein Array zu initialisieren bedeutet, dem Array Werte zuzuweisen. Lassen Sie uns die Arrays initialisieren, die wir im vorherigen Abschnitt deklariert haben:
String[] names = {"John", "Jade", "Love", "Allen"};
int[] myIntegers = {10, 11, 12};
Wir haben unsere Arrays initialisiert, indem wir Werte desselben Datentyps übergeben und jeden Wert durch ein Komma getrennt haben. Wenn wir auf die Elemente/Werte in unserem Array zugreifen wollten, würden wir auf deren Indexnummer im Array zugreifen. Der Index des ersten Elements ist 0. Hier ein Beispiel:
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
Nachdem wir nun wissen, wie wir auf jedes Element zugreifen, ändern wir den Wert des dritten Elements.
String[] names = {"John", "Jade", "Love", "Allen"};
names[2] = "Victor";

System.out.println(names[2]);
// Victor
Wir können die Länge eines Arrays auch mithilfe der Längeneigenschaft überprüfen . Hier ist ein Beispiel:
String[] names = {"John", "Jade", "Love", "Allen"};
System.out.println(names.length);
// 4

So durchlaufen Sie ein Array in Java

Wir können eine for- Schleife verwenden, um die Elemente eines Arrays zu durchlaufen .
String[] names = {"John", "Jade", "Love", "Allen"};
for (int i = 0; i < names.length; i++) {
  System.out.println(names[i]);
}

// John
// Jade
// Love
// Allen
Die obige Schleife gibt die Elemente unseres Arrays aus. Wir haben die Längeneigenschaft verwendet , um anzugeben, wie oft die Schleife ausgeführt werden soll.

Abschluss

In diesem Artikel haben wir gelernt, wie man Arrays in Java-Code deklariert und initialisiert. Wir haben auch gesehen, wie man auf jedes Element eines Arrays zugreift und wie man diese Elemente in einer Schleife durchläuft. Viel Spaß beim Codieren!

Wie kann ich einen Java-Thread stoppen, ohne Thread.stop() zu verwenden?

Quelle: 4comprehension Wenn Sie dies lesen, fragen Sie sich wahrscheinlich, warum und vor allem wie man einen Thread stoppt, wenn man sich nicht einfach auf die Thread#stop()- Methode verlassen kann, die seit Java 1.2 veraltet ist ? Kaffeepause Nr. 112.  So deklarieren, initialisieren und iterieren Sie über ein Array in Java.  Wie kann ich einen Java-Thread stoppen, ohne Thread.stop() zu verwenden?  - 2Die kurze Antwort lautet, dass Sie Unterbrechungen verwenden sollten, da Thread#stop unsicher ist. Wenn Sie jedoch verstehen möchten, warum, wie und wofür diese lästige InterruptedException gedacht ist , lesen Sie weiter.

Problem mit Thread#stop()

So intuitiv es auch klingen mag, das Unterbrechen, Starten und Stoppen eines bereits laufenden Threads sind zwei völlig unterschiedliche Fälle. Warum? Wenn wir einen neuen Thread starten, beginnen wir bei Null, was ein klar definierter Zustand ist. Wenn wir jedoch versuchen, einen vorhandenen Thread zu stoppen, kann dies mitten in einem Vorgang passieren, der nicht sofort unterbrochen werden kann . Stellen Sie sich einen Thread vor, der Änderungen an einer Thread-sicheren Datenstruktur vornimmt. Während er sich in der Mitte des kritischen Abschnitts befindet ... und dann der Thread auf magische Weise verschwindet, werden die Sperren aufgehoben, und jetzt kann ein anderer Thread die Datenstruktur beobachten, die in einem inkonsistenten Zustand verbleibt. Betrachten Sie das folgende Beispiel eines Thread-sicheren Zählers mit einem internen Status:
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;
    }
}
Wie Sie sehen können, erhöht die Methode getAndIncrement() den Zähler und ändert das Dirty- Flag . Sperren stellen sicher, dass jedes Mal, wenn ein Thread getAndIncrement() aufruft, das Dirty- Flag auf false gesetzt wird . Jetzt erstellen wir einen Thread und beenden ihn abrupt:
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
Jetzt ist die threadSafeCounter- Instanz trotz korrekter Implementierung dauerhaft beschädigt, da der Thread abrupt gestoppt wurde. Wie man es repariert?

Kooperative Thread-Unterbrechung

Anstatt den Thread zu stoppen, sollten wir uns auf eine kooperative Thread-Unterbrechung verlassen. Einfach ausgedrückt müssen wir den Thread mit Thread#interrupt auffordern, sich im richtigen Moment selbst zu stoppen . Der Aufruf von Thread#interrupt anstelle von Thread#stop reicht jedoch nicht aus. Eine sichere Beendigung eines Threads kann nur durch die Verwendung eines gemeinsam genutzten Thread-Interrupts erreicht werden. Das bedeutet, dass wir innerhalb des Threads Interrupt-Signale verarbeiten müssen, die in zwei Arten vorliegen:
  • Boolesche Unterbrechungsflagge

  • InterruptedException

Handhabung unterbrechbarer Flags

Während wir uns in einem Thread befinden, können wir überprüfen, ob er unterbrochen wurde, indem wir eine der folgenden Methoden aufrufen:
Thread.currentThread().isInterrupted(); // reads the interrupted flag
Thread.interrupted(); // reads and resets the interrupted flag
Da es keine universelle Möglichkeit gibt, mit einem Interrupt umzugehen, müssen wir eine Aktion anwenden, die zu unserem Kontext passt. Im Beispiel aus dem vorherigen Abschnitt erhöht der Thread unseren Zähler in einer Endlosschleife. Anstatt sofort anzuhalten, könnten wir einfach warten, bis der Thread seine aufsteigende Arbeit abgeschlossen hat, und dann die Schleife verlassen:
var threadSafeCounter = new ThreadSafeCounter();

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

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

threadSafeCounter.incrementAndGet();
Jetzt wird der Thread zum richtigen Zeitpunkt sicher beendet, ohne Chaos zu verursachen.

Behandlung von InterruptedException

Was passiert, wenn wir versuchen, einen wartenden Thread zu unterbrechen? Natürlich können wir das Unterbrechungsflag nicht berücksichtigen , da der Thread mit einer blockierenden Operation beschäftigt ist. Aus diesem Grund gibt es InterruptedException . Dies ist keine Standardausnahme, sondern eine andere Form eines Interrupt-Signals, das ausschließlich zur Verarbeitung blockierender Interrupts dient! Wie Thread#interrupted setzt es das Unterbrechungsflag zurück . Lassen Sie uns das obige Beispiel noch einmal ändern und vor jedem Inkrement Pausen einführen. Jetzt müssen wir die von Thread#sleep ausgelöste InterruptedException behandeln :
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);
In unserem Fall reichte es aus, die Schleife einfach zu verlassen. Aber was ist, wenn Sie nicht der Meinung sind, dass eine bestimmte Methode für die Behandlung von Interrupts verantwortlich sein sollte? Was ist, wenn die Methodensignatur nicht geändert werden kann? In diesem Fall müssen wir das Unterbrechungsflag wiederherstellen und/oder die Ausnahme neu verpacken, zum Beispiel:
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    throw new RuntimeException(e);
}

Abschluss:

  • Thread#stop ist nicht ohne Grund veraltet – es ist tatsächlich sehr unsicher.

  • Threads werden durch Unterbrechungen gestoppt – Signale, die vom Thread selbst interpretiert werden.

  • InterruptedException ist keine gewöhnliche Ausnahme – es ist Javas integrierte Methode, um zu signalisieren, dass ein Thread unterbrochen wurde.

  • Thread.currentThread().isInterrupted() und Thread.interrupted() sind nicht dasselbe. Der erste liest einfach das Unterbrechungsflag , der andere setzt es anschließend zurück.

  • Es gibt keine universelle Möglichkeit, mit Interrupt-Signalen umzugehen – „es hängt von den Umständen ab.“

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