JavaRush /Blog Java /Random-FR /Pause café #112. Comment déclarer, initialiser et parcour...

Pause café #112. Comment déclarer, initialiser et parcourir un tableau en Java. Comment arrêter un thread Java sans utiliser Thread.stop() ?

Publié dans le groupe Random-FR

Comment déclarer, initialiser et parcourir un tableau en Java

Source : FreeCodeCamp Dans cet article, nous parlerons des tableaux en Java. Nous examinerons quelques exemples pour vous aider à comprendre ce qu'est un tableau, comment le déclarer et comment l'utiliser dans le code Java. Pause café #112.  Comment déclarer, initialiser et parcourir un tableau en Java.  Comment arrêter un thread Java sans utiliser Thread.stop() ?  - 1

Qu'est-ce qu'un tableau ?

En Java, nous utilisons un tableau pour stocker plusieurs valeurs du même type de données dans une seule variable. Il peut également être considéré comme un ensemble de valeurs du même type de données. Cela signifie que si vous souhaitez stocker des chaînes dans votre tableau, par exemple, toutes les valeurs de votre tableau doivent être des chaînes.

Comment déclarer un tableau en Java

Nous utilisons des crochets [ ] pour déclarer un tableau . Comme ça:
String[] names;
Ici, nous avons déclaré une variable appelée noms qui contiendra un tableau de chaînes. Si nous devons déclarer une variable pour les entiers (entiers), alors nous le ferons comme ceci :
int[] myIntegers;
Ainsi, pour créer un tableau, nous spécifions le type de données qui seront stockées dans le tableau, suivi de crochets puis du nom du tableau.

Comment initialiser un tableau en Java

Initialiser un tableau signifie attribuer des valeurs au tableau. Initialisons les tableaux que nous avons déclarés dans la section précédente :
String[] names = {"John", "Jade", "Love", "Allen"};
int[] myIntegers = {10, 11, 12};
Nous avons initialisé nos tableaux en passant des valeurs du même type de données, en séparant chaque valeur par une virgule. Si nous voulions accéder aux éléments/valeurs de notre tableau, nous accéderions à leur numéro d'index dans le tableau. L'index du premier élément est 0. Voici un exemple :
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
Maintenant que nous savons comment accéder à chaque élément, modifions la valeur du troisième élément.
String[] names = {"John", "Jade", "Love", "Allen"};
names[2] = "Victor";

System.out.println(names[2]);
// Victor
Nous pouvons également vérifier la longueur d'un tableau en utilisant la propriété length . Voici un exemple :
String[] names = {"John", "Jade", "Love", "Allen"};
System.out.println(names.length);
// 4

Comment parcourir un tableau en Java

Nous pouvons utiliser une boucle for pour parcourir les éléments d’un tableau .
String[] names = {"John", "Jade", "Love", "Allen"};
for (int i = 0; i < names.length; i++) {
  System.out.println(names[i]);
}

// John
// Jade
// Love
// Allen
La boucle ci-dessus imprimera les éléments de notre tableau. Nous avons utilisé la propriété length pour spécifier combien de fois la boucle doit être exécutée.

Conclusion

Dans cet article, nous avons appris comment déclarer et initialiser des tableaux en code Java. Nous avons également vu comment accéder à chaque élément d’un tableau et comment parcourir ces éléments. Bon codage !

Comment arrêter un thread Java sans utiliser Thread.stop() ?

Source : 4comprehension Si vous lisez ceci, alors vous vous demandez probablement pourquoi, et surtout, comment arrêter un thread si vous ne pouvez pas vous fier uniquement à la méthode Thread#stop() , qui est obsolète depuis Java 1.2. ? Pause café #112.  Comment déclarer, initialiser et parcourir un tableau en Java.  Comment arrêter un thread Java sans utiliser Thread.stop() ?  - 2La réponse courte est que vous devez utiliser des interruptions car Thread#stop n'est pas sûr. Mais si vous voulez comprendre pourquoi, comment et à quoi sert cette satanée InterruptedException , continuez à lire.

Problème avec le fil#stop()

Aussi intuitif que cela puisse paraître, interrompre un thread déjà en cours d'exécution, le démarrer et l'arrêter sont deux cas complètement différents. Pourquoi? Lorsque nous démarrons un nouveau thread, nous repartons de zéro, ce qui est un état bien défini, mais lorsque nous essayons d'arrêter un thread existant, cela peut se produire au milieu d'une opération qui ne peut pas être interrompue immédiatement . Imaginez un thread apportant des modifications à une structure de données thread-safe. Alors qu'il se trouve au milieu de la section critique... puis le thread disparaît comme par magie - les verrous sont libérés, et maintenant un autre thread peut observer la structure de données laissée dans un état incohérent. Prenons l'exemple suivant d'un compteur thread-safe avec un état interne :
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;
    }
}
Comme vous pouvez le voir, la méthode getAndIncrement() incrémente le compteur et modifie le drapeau sale . Les verrous garantissent que chaque fois qu'un thread entre dans getAndIncrement(), l' indicateur sale est défini sur false . Créons maintenant un fil de discussion et arrêtons-le brusquement :
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
Désormais, l' instance de threadSafeCounter , bien qu'elle soit correctement implémentée, est définitivement corrompue en raison de l'arrêt brusque du thread. Comment le réparer?

Interruption du fil de discussion coopératif

Au lieu d’arrêter le thread, nous devrions nous appuyer sur une interruption coopérative du thread. En termes simples, il faut demander au thread de s'arrêter au bon moment en utilisant Thread#interrupt . Cependant, appeler Thread#interrupt au lieu de Thread#stop ne suffit pas. La terminaison sécurisée d'un thread ne peut être obtenue qu'en utilisant une interruption de thread partagée, ce qui signifie que dans le thread, nous devons gérer les signaux d'interruption, qui sont de deux types :
  • Indicateur booléen interrompu

  • Exception interrompue

Gestion des indicateurs d'interruption

À l'intérieur d'un thread, nous pouvons vérifier s'il a été interrompu en appelant l'une des méthodes :
Thread.currentThread().isInterrupted(); // reads the interrupted flag
Thread.interrupted(); // reads and resets the interrupted flag
Puisqu’il n’existe pas de méthode universelle pour gérer une interruption, nous devons appliquer une action adaptée à notre contexte. Dans l'exemple de la section précédente, le thread incrémente notre compteur dans une boucle infinie. Au lieu de s'arrêter immédiatement, nous pourrions simplement attendre que le thread termine son travail ascendant puis quitter la boucle :
var threadSafeCounter = new ThreadSafeCounter();

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

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

threadSafeCounter.incrementAndGet();
Désormais, le fil se termine en toute sécurité au bon moment sans provoquer de chaos.

Gestion des exceptions interrompues

Que se passe-t-il si nous essayons d'interrompre un thread en attente ? Bien entendu, nous ne pouvons pas prendre en compte le flag d'interruption car le thread est occupé par une opération de blocage. C'est pourquoi InterruptedException existe . Il ne s'agit pas d'une exception standard, mais d'une forme différente de signal d'interruption qui existe uniquement pour gérer les interruptions bloquantes ! Comme Thread#interrupted , il réinitialise l' indicateur d'interruption . Modifions à nouveau l'exemple ci-dessus et introduisons des pauses avant chaque incrément. Nous devons maintenant gérer l'InterruptedException levée par 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);
Dans notre cas, il suffisait simplement de sortir de la boucle. Mais que se passe-t-il si vous ne pensez pas qu'une méthode spécifique devrait être responsable de la gestion des interruptions ? que se passe-t-il si la signature de la méthode ne peut pas être modifiée ? Dans ce cas, nous devons restaurer l' indicateur d'interruption et/ou reconditionner l'exception, par exemple :
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    throw new RuntimeException(e);
}

Conclusion:

  • Thread#stop n'est pas obsolète sans raison - il est en fait très peu sécurisé.

  • Les threads sont arrêtés par des interruptions – des signaux interprétés par le thread lui-même.

  • InterruptedException n'est pas une exception ordinaire - c'est le moyen intégré à Java de signaler qu'un thread a été interrompu.

  • Thread.currentThread().isInterrupted() et Thread.interrupted() ne sont pas la même chose. Le premier lit simplement le drapeau d'interruption , et l'autre le réinitialise ensuite.

  • Il n’existe pas de méthode universelle pour gérer les signaux d’interruption : « cela dépend des circonstances ».

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