Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > fr.comp.lang.java > #1711

Re: Terminer un Thread.

Path csiph.com!eternal-september.org!feeder.eternal-september.org!news.trigofacile.com!.POSTED.reverse-90.fdn.fr!not-for-mail
From Yliur <yliur@free.fr>
Newsgroups fr.comp.lang.java
Subject Re: Terminer un Thread.
Date Sat, 15 Sep 2018 14:24:21 +0200
Organization Groupes francophones par TrigoFACILE
Message-ID <20180915142421.339f4019@free.fr> (permalink)
References <5b9992bb$0$5486$426a74cc@news.free.fr> <pnc4mh$cmk$1@dont-email.me> <20180913012022.478eee8b@free.fr> <5b99d812$0$20328$426a74cc@news.free.fr> <20180913073148.135d0f4f@free.fr> <5b9ae7e6$0$15086$426a74cc@news.free.fr> <20180914054630.010fc8ab@free.fr> <5b9ca997$0$15518$426a74cc@news.free.fr>
Mime-Version 1.0
Content-Type text/plain; charset=UTF-8
Content-Transfer-Encoding 8bit
Injection-Info news.trigofacile.com; posting-account="yliur@free.fr"; posting-host="reverse-90.fdn.fr:80.67.176.90"; logging-data="8835"; mail-complaints-to="abuse@trigofacile.com"
X-Newsreader Claws Mail 3.17.1 (GTK+ 2.24.32; x86_64-pc-linux-gnu)
Xref csiph.com fr.comp.lang.java:1711

Show key headers only | View raw


Le 15 Sep 2018 06:41:27 GMT
jp <bloiiing@yahoo.invalid> a écrit :

> Le Fri, 14 Sep 2018 05:46:30 +0200, Yliur a écrit :
> 
> 
> > 
> > Là l'élément important c'est est-ce que la boucle est très longue
> > parce qu'elle réalise un traitement actif (des instructions sont
> > exécutées en permanence) ou bien elle est longue parce que le fil
> > est bloqué à différents moment ?  
> 
> Il y a deux delay à l'intérieur d la boucle infinie qui peuvent durer 
> plusieurs minutes chacun.
> 
> > 
> > Dans le deuxième cas, quelles sont les opérations bloquantes ? Il y
> > a des chances pour qu'elles répondent aux interruptions des fils
> > d'exécution via la mécanique de java (interrupt()).  
> 
> Je ne sais pas... Je vais essayer de remplacer les delay, qui sont
> des méthodes implémentées par l'API spécifique que j'utilise, par des 
> Thread.sleep(n); pour voir...
> 
> > 
> > Suivant ton cas, j'essaierai d'expliquer plus en détail ce que tu
> > peux faire. La doc plus complète sur le sujet se trouve ici, mais
> > c'est un peu touffu :) :
> >     <https://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/
> threadPrimitiveDeprecation.html>
> >   
> 
> Merci pour le lien. En fait ce que je veux faire est simple. J'ai une 
> carte qui comporte 4 relais branchée sur un raspberry. J'utilise une 
> bibliothèque écrite en C et une API écrite en Java qui utilise cette 
> bibliothèque. J'écris un petit programme qui mes les relais sur ON 
> pendant un certain nombre de secondes et sur OFF une autre durée.
> Comme il y a 4 relais, j'ai créé 4 threads. J'arrive à allumer les
> relais. J'arrive aussi à les éteindre. Mais par contre lorsque je
> quitte le programme, les relais restent dans leur état. Quelquefois
> sur ON et quelquefois sur OFF...
> 
> Il faut dire que je ne maitrise pas très bien les threads. Mais ce
> que je veux faire n'est pas très compliqué. Je pense que je vais m'en
> sortir. 
> > 
> > Il faudra bien faire attention quand même :
> >     - Ne pas détruire le fil brutalement (avec Thread.stop(), qui de
> >       toutes façons est obsolète).
> >     - Utiliser un try/finally, pour être sûr que la finalisation
> > soit réalisée.  
> 
> Je ne connais pas l'utilisation de try/finally mais je vais me
> documenter sur ce sujet. Merci de m'avoir montré la direction dans
> laquelle chercher. 
> 
> > Suivant ce que tu veux dire par "n'existe pas" :
> >     - Si tu n'as pas initialisé la variable (elle vaut null) : non,
> > tu vas avoir une NullPointException.
> >     - Si le fil n'a simplement pas été lancé (via start()) : oui,
> >       d'après la doc
> >       (<https://docs.oracle.com/javase/6/docs/api/java/lang/
> Thread.html#isAlive()>)
> >       (le fil est en vie s'il a été démarré mais n'est pas encore
> > mort) 
> 
> Si je fais un interrupt(), dans quel état se trouvera mon thread?
> Est-ce qu'il sera encore actif? Ou est-ce qu'il sera  égal à null?
> 
> Je reposte le code de mon thread:
> 
> -----début du code-----
> import com.pi4j.wiringpi.*;
> 
> /**
>  *
>  * @author jp
>  */
> public class ShroomThread extends Thread {// throws
> InterruptedException { 
>     long ms_on, ms_off;
>     int pinmode;
>     //boolean isRunning = true;
>     
>     ShroomThread( long on, long off, int pin ) {
>         this.ms_on = on;
>         this.ms_off = off;
>         this.pinmode = pin;
>         Gpio.pinMode( pinmode, Gpio.OUTPUT );
>     }
>     
>     public void setGpioLow() {
>         Gpio.digitalWrite( pinmode, Gpio.LOW );
>     }
>     /**
>      *
>      */
>     @Override
>     public void run() {
> 
>         try {
>             while ( true ) {
>                 if ( interrupted() ) {
>                     throw new InterruptedException();
>                 }
>                 Gpio.digitalWrite( pinmode, Gpio.HIGH );
>                 Gpio.delay( ms_on );
>                 Gpio.digitalWrite( pinmode, Gpio.LOW );
>                 Gpio.delay( ms_off );
>             }
>         }
>         catch ( InterruptedException e ) {}
>     }
> }
> -----fin du code-----
> 
> Dans la classe principale, je fais:
> 
> if ( t1 != null ) { t1.setGpioLow(); t1.interrupt(); }
> 
> ou bien:
> 
> if ( t1.isAlive() ) { t1.setGpioLow(); t1.interrupt(); }
> 
> Qu'est-ce qu'il vaut mieux?
> 
> A+

D'accord, je vois un peu mieux ce que tu veux faire.

Effectivement, je ne sais pas si Gpio.delay va réagir à interrupt : il
faudrait voir la doc ou bien faire un essai (mais la doc c'est mieux).
A priori InterruptedException est une "exception contrôlée" : tu aurais
une erreur de compilation dans ton code d'origine (celui sans "catch
( InterruptedException e )") si cette fonctions était capable de réagir
aux interruptions et qu'elle levait des InterruptedException. Sauf si
je manque quelque chose, elle ne sait pas le faire.

Donc tu as effectivement des traitements courts, entrecoupés de pauses
plus ou moins longues. Dans ce cas le code que tu as écrit ici
convient : tu vérifies si le fil est interrompu et tu quittes la boucle
(une exception pourquoi pas : ça permet de traiter tous les cas
d'interruption de la même manière). Si tu utilises Thread.sleep(),
l'attente sera effectivement interrompue par une InterruptedException
en cas de demande d'interruption du fil.

Dans la fonction run, tu peux écrire ça :
    try
    {
        <le code actuel>
    }
    finally
    {
        <mettre le relais dans l'état final souhaité>
    }

De cette manière, quand le code dans le try se terminera (normalement,
par une exception, même par un return, peu importe), ce qui se trouve
dans finally sera immédiatement exécuté. C'est donc là que tu veux
mettre le code permettant de remettre ton relais dans l'état final
souhaité. Attention si certaines opérations de finalisation sont
elles-mêmes susceptibles de lever des exceptions : il faut décider que
faire si ce cas se produit (par défaut le code du finally
s'interrompra, comme tout autre code qui rencontre une erreur).

Note que si tu fermes violemment ton programme depuis l'extérieur
tout ça ne sera sans doute pas exécuté : mieux vaut un moyen de lui
indiquer gentiment de se terminer et qu'il interrompe tous ses
traitement en cours. Si tu tues la JVM depuis l'extérieur, les
traitements de finalisation replaçant les relais dans le bon état ne
pourront pas s'exécuter. Pour plus de précisions, il faudrait savoir
comment tu utilises ton programmes / ce que tu veux en faire.

Depuis l'extérieur :
    - À moins que tu en aies vraiment besoin, tu devrais éviter d'avoir
      des variables t1 == null, ça simplifierait tes problèmes. Mais ça
      dépend de ce que tu veux faire avec des fils d'exécution.
    - Je ne sais pas à quoi sert t1.setGpioLow(); : s'il s'agit du code
      permettant de replacer le relais dans son état final, voir
      les remarques ci-dessus.
    - A priori le fil sera considéré comme mort une fois interrompu
      (parce qu'il aura terminé l'exécution de sa méthode run).
      Et donc t1.isAlive() reverra faux. D'après la doc, tu ne peux pas
      relancer un fil qui s'est terminé (qui est mort), mais tu peux
      toujours en recréer un via new ShroomThread (...).
    - Lorsque le fil sera interrompu, la variable qui contient une
      référence sur l'objet ShroomThread ne passera pas toute seule à
      null. Donc t1 == null sera toujours faux.

Pour plus de précisions sur la gestion des fils depuis l'extérieur, il
faudrait savoir quel est le but exact de la manœuvre (est-ce que tu
veux parfois les relancer, dans quelles conditions, ... ?).

À propos du reste de ton code :
    - Les classes ne déclarent pas d'exceptions, la ligne
      throws InterruptedException (en commentaire) ne peut pas servir à
      cet endroit.
    - En général on définit les attributs des classes comme privés
      (private int ...), ce qui évite d'y accéder malencontreusement
      depuis l'extérieur.

Back to fr.comp.lang.java | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

Terminer un Thread. jp <bloiiing@yahoo.invalid> - 2018-09-12 22:27 +0000
  Re: Terminer un Thread. Samuel DEVULDER <samuel.devulder@laposte-dot-net.invalid> - 2018-09-13 00:41 +0200
    Re: Terminer un Thread. Yliur <yliur@free.fr> - 2018-09-13 01:20 +0200
      Re: Terminer un Thread. jp <bloiiing@yahoo.invalid> - 2018-09-13 03:22 +0000
        Re: Terminer un Thread. Yliur <yliur@free.fr> - 2018-09-13 07:31 +0200
          Re: Terminer un Thread. jp <bloiiing@yahoo.invalid> - 2018-09-13 22:42 +0000
            Re: Terminer un Thread. Yliur <yliur@free.fr> - 2018-09-14 05:46 +0200
              Re: Terminer un Thread. jp <bloiiing@yahoo.invalid> - 2018-09-15 06:41 +0000
                Re: Terminer un Thread. Yliur <yliur@free.fr> - 2018-09-15 14:24 +0200
                Re: Terminer un Thread. jp <bloiiing@yahoo.invalid> - 2018-09-16 03:09 +0000

csiph-web