1
votes

Arrête l'exécution du thread lorsqu'il appelle url.openStream () dans une boucle

Modifier : je sais ce que fait Thread.interrupt ().

  • while (! Thread.currentThread (). isInterrupted ()) ne se ferme pas lorsque j'interrompt le fil.
  • J'ai également essayé d'attraper une exception de url.openStream (); quand le le fil est interrompu (désespoir, c'était peut-être une méthode de blocage, ce qui n'est pas le cas) et quittez la boucle, sans succès.

L'application crée un Thread qui lit en continu une URL . Après 3 secondes, Thread est interrompu mais continue malheureusement de s'exécuter.

Comment arrêter le thread de s'exécuter?

Code (Main.java, MyRunnable.java):

public class Main {

    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable("http://ninjaflex.com/");
        Thread thread = new Thread(runnable);
        thread.start();
        sleep(3000);
        thread.interrupt();
        System.out.println("Thread.interrupt() invoked.");
    }

    private static void sleep(long timeMilli) {
        try {
            Thread.sleep(timeMilli);
        } catch (Exception e) {

        }
    }
}

public class MyRunnable implements Runnable {

    private String website;

    MyRunnable(String website) {
        this.website = website;
    }

    @Override
    public void run() {
        URL url = createUrl();
        if (url != null) {
            while (!Thread.currentThread().isInterrupted()) {
                sleepOneSec();
                readFromUrl(url);
                System.out.println("Read from " + website);
            }
            System.out.println("Script: Interrupted, exiting.");
        }
    }

    private URL createUrl() {
        URL url = null;
        try {
            url = new URL(website);
        } catch (MalformedURLException e) {
            System.out.println("Wrong URL?");
        }
        return url;
    }

    private void sleepOneSec() {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            System.out.println("Error sleeping");
        }
    }

    private void readFromUrl(URL url) {
        InputStream in = null;
        try {
            in = url.openStream();
        } catch (Exception e) {
            System.out.println("Exception while url.openStream().");
            e.printStackTrace();
        } finally {
            closeInputStream(in);
        }
    }

    private void closeInputStream(InputStream in) {
        try {
            in.close();
        } catch (IOException e) {
            System.out.println("Error while closing the input stream.");
        }
    }
}


1 commentaires

Je sais ce que Thread.interrupt () fait cher @ PM77-1, mais si j'ai fait quelque chose de mal ici, merci de le partager.


3 Réponses :


2
votes

En gros, votre thread MyRunnable est interrompu pendant le sommeil. InterreuptedException est lancé mais intercepté. Soit dit en passant, c'est une mauvaise habitude d'attraper Exception et vous ne devriez pas le faire. Depuis le javadoc: "L'état interrompu du thread actuel est effacé lorsque cette exception est levée". Par conséquent, votre boucle while ne verra jamais le drapeau.


2 commentaires

Oh, je n'ai pas vu cela venir. Laissez-moi vérifier en supprimant le sommeil. Mais cela semble logique. Merci pour la contribution.


Ok j'ai raté ce scénario: "Si ce thread est bloqué lors d'un appel des méthodes wait (), wait (long) ou wait (long, int) de la classe Object, ou de la join () , join (long), join (long, int), sleep (long) ou sleep (long, int), méthodes de cette classe, alors son état d'interruption sera effacé et il recevra un InterruptedException. ". Merci encore.



0
votes

J'ai supprimé MyRunnable.sleepOneSec et votre code a commencé à fonctionner.


1 commentaires

Oui, c'est la solution. Le sleep () captait l'interruption mais ensuite l'état de l'interruption a été effacé donc la boucle n'a pas pu être quittée.



1
votes

Remplacez l'appel à la méthode sleepOneSec par un simple appel Thread.sleep. Attrapez InterruptedException en dehors de votre boucle while . Cela entraînera la fermeture naturelle de la boucle:

try {
    while (true) {
        Thread.sleep(1000);
        readFromUrl(url);
        System.out.println("Read from " + website);
    }
} catch (InterruptedException e) {
    System.out.println("Script: Interrupted, exiting.");
}


4 commentaires

Oui, cela fera l'affaire. Mais je m'en fiche de supprimer l'appel de sommeil. Pour être honnête, je l'ai mis là pour ne pas être bombardé par des bûches.


Bombardé par "Script: Interrompu, sortant" vous voulez dire? Changez-le simplement en System.getLogger (Main.class.getName ()). Log (System.Logger.Lev‌ el.DEBUG, "Script: Interrupted, exit.", E); donc c'est visible uniquement si vous modifiez la configuration de la journalisation.


Merci beaucoup @VGR!


Croiriez-vous que j'ai le même morceau de code dans une application Android et que l'exécution du thread ne s'arrête pas? Astuce, il n'y a pas de Thread.sleep () ici. Demandera probablement une fois de plus.