Thread questions

Conception de logiciels Intranet : patrons et canevas

Moderators: douinj, graffiop

Post Reply
guill_f58
Posts: 68
Joined: 10 Oct 2020 19:42

Thread questions

Post by guill_f58 » 19 Feb 2022 21:10

Bonsoir, j'ai commencé à voir le cours sur les threads et j'ai quelques questions (en vracs ci dessous).
J'aimerais avoir des réponses/confirmations sur ce que j'écris, merci.

//////////////////////////////////
La méthode "start()" permet-elle de mettre un thread dans la file d'attente de l'ordonnanceur ?
Cela ne veut pas dire que le traitement du thread sera immédiat.

Un thread "not alive" est-il un thread qui n'a pas subis la fonction "start()" ce qui rend éligible le thread à l'exécution d'une tâche ?

Ce code contient 4 threads (main, t1, t2, t3) :

Code: Select all

    public static void main(String[] args) throws InterruptedException {
        T t1 = new T();
        T t2 = new T();
        T t3 = new T();
C'est le thread "main" qui s'occupe d'exécuter les méthodes interrupt() et start() sur les objets t1, t2 et t3.
Quand on utilise "Thread.sleep()" dans le main, on endort le thread du main, c’est-à-dire que pendant x temps, les threads qui ont pu démarrer tournent en boucle.
La méthode "interrupt()" permet de changer le flag (false true) du thread.
Ce dernier pourra s'arrêter immédiatement s'il est dans un état bloquant (sleep, wait) et propager une exception. Où bien éventuellement plus tard ou jamais tant que la méthode "interrupted()" du thread n'est pas exécuté. Cette dernière réinitialisera le flag (true false).
Cas de figure d'un thread démarré que je veux arrêter :
-"start()" qui met mon thread à disposition de l'ordonnanceur.
-"interrupt()" qui colle une étiquette (un mandat d'arrêt) sur mon thread pour lui dire de s'arrêter dès que c'est possible.
-la méthode "run()" qui s'exécute quand l'ordonnanceur donne un temps d'exécution au thread.
Cette dernière déclenche la méthode "interrupted()" (la police) qui en fonction de l'utilisation précédente ou non de "interrupt()" arrêtera le programme.

Si je fais "interrupted" sur un thread qui a eu "start()", voir l'exemple précédent.
Si je fais "interrupted" sur un thread qui n'a jamais eu de "start()", il ne se passe strictement rien.
Si je fais "interrupted" sur un thread qui est en attente/bloqué, il s'arrête et il y a propagation d'une erreur. D'ailleurs, est ce que c'est ce qui se passe à la page 15 ? je tente d'interrompre t3 pendant qu'il est entrain de dormir ce qui déclenche une exception.


Example p 13, j'ai rajouté ceci :

Code: Select all

    @Override
    public void run() {
        while(!this.interrupted()) {
            //blabla
        }
        System.out.println("arrêt");
    }
    @Override
    public void interrupt() {
        System.out.println("interrupting "+this);
        super.interrupt();
    }
En résultat j'ai :

Code: Select all

interrupting Thread[Thread-0,5,main]    [LIGNE1]
interrupting Thread[Thread-1,5,main]     [LIGNE2]
arrêt     [LIGNE3]
dans Exemple.main     [LIGNE4]
interrupting Thread[Thread-2,5,main]      [LIGNE5]
dans Thread[Thread-2,5,main] .run  ]     [LIGNE6]
arrêt  ]     [LIGNE7]
Ligne 1 : correspond à t1.interrupt();
Ligne 2 + ligne 3: on change le flag du thread et on ne rentre jamais dans le while de run().
L'ordonnanceur a exécuté interrupt() avant le run.
ligne 5 + 6 + 7 : L'ordonnanceur a exécuté le run avant interrupt(), c'est pour cela qu'on a la ligne 6 suivis d'arrêt ligne 7.

Est-ce-que c'est bien cela qui différencie l2+l3 par rapport à l5+l6+l7 ?

Pourquoi quand j'exécute le code suivant je n'ai qu'un seul interrupted sur le dernier thread et aucun autre ?
Qu est il arrivé aux autres ?

Code: Select all

        t1.interrupt();//lu puis arrêt (bool à false)
        //mise à disposition dans la liste pour l'ordonnanceur
        t2.start();

        t2.interrupt();//lu puis arrêt
        //mise à disposition dans la liste pour l'ordonnanceur
        t3.start();

        System.out.println("dans Exemple.main");
        Thread.sleep(2000);
        System.out.println("is sleeping");
//////////////////////////////////

Je continuerais demain avec la suite. Pour faire le TP Thread, il faut avoir vu tout le document en question ?
Bonne soirée / journée

guill_f58
Posts: 68
Joined: 10 Oct 2020 19:42

Re: Thread questions

Post by guill_f58 » 20 Feb 2022 19:42

Autre question. J'ai un petit exemple qui utilise sleep, interrupt et interrupted (en dehors du cours) :

Code: Select all

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new InterruptableTwice());
        t.start();
        System.out.println("Thread is interrupted : " + t.isInterrupted());
        t.interrupt();
        Thread.sleep(1000);

        System.out.println("Thread is interrupted : " + t.isInterrupted());
        t.interrupt();
        Thread.sleep(1000);
    }
}

class InterruptableTwice implements Runnable {
    int count = 2;

    public void run() {
        System.out.println("Runnable started");
        while (true) {
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("Hey someone interrupted me !!!");
                count -=1;

                Thread.interrupted();
                if (count == 0) {
                    System.out.println("Ok, game over !!!");
                    break;
                }
            }
        }
    }
}

Runnable started
Thread is interrupted : false
Hey someone interrupted me !!!
//petite pause
Thread is interrupted : false
Hey someone interrupted me !!!
Ok, game over !!!
La méthode interrupt() change le 'flag' associé au thread (false ==> true).
C'est une manière de dire "J'aimerais m'arrêter dès que possible...".
Pour que cette demande soit honorée, il y a plusieurs manières.
Par exemple, si mon thread exécute la méthode "interrupted()", normalement il doit s'arrêter.
Cette dernière doit arrêter (mais pas supprimer ?) et réinitialiser son tag (true ==> false).
De même, si "sleep()" peut checker cette valeur et si c'est le cas, il déclencera une exception.

Sleep() est associé au main donc il n'y a pas d'interruption. Mais mon thread rencontre rencontre interrupt et interrupted 2 fois, pourquoi ne s'arrête t il pas ?
La première fois, il met le thread à l'arrêt sans le détruire et change son flag. Mais comme le thread est encore utilisé par le deuxième interrupt(), il relance le run une deuxième fois? C'est pour cela qu'il n'y a toujours isInterruped() à false et qu'il peut faire un count = 2.

Post Reply