Comment interrompre une Boucle Infinie

même si je sais que ce sera un peu bête de demander, je veux quand même en savoir plus sur la perspective technique de celui-ci.

exemple simple d'une boucle infinie:

public class LoopInfinite {
    public static void main(String[] args) {
        for (;;) {
            System.out.println("Stack Overflow");
        }
    }
}

Comment puis-je interrompre (arrêter) cette boucle infinie en dehors de cette classe (par exemple, avec l'aide de l'héritage)?

24
demandé sur Boann 2012-08-17 12:35:16

12 réponses

je me sens sale même en écrivant ceci, mais...

à partir d'un fil différent, vous pouvez appeler System.setOut() avec une implémentation PrintStream , qui lance un RuntimeException quand vous appelez println() .

49
répondu David Grant 2012-08-17 11:45:20

nous pouvons l'atteindre en utilisant la variable volatile , que nous allons changer hors de Thread et arrêter la boucle.

   for(;!cancelled;) /*or while(!cancelled)*/{
       System.out.println("Stackoverflow");
   }

c'est une meilleure façon d'écrire boucle infinie.

public class LoopInfinite{
      private static volatile boolean cancelled=false;
      public static void main(String[] args){
             for(;!cancelled;) { //or while(!cancelled)
                    System.out.println("Stackoverflow");
             }
      }
      public void cancel(){
        cancelled=true;
      }
}
26
répondu Subhrajyoti Majumder 2017-05-12 15:35:25

Vous peut obtenir le thread qui exécute la boucle infinie à partir d'un autre thread et call interrompre. Vous devrez être très sûr de ce que vous faites cependant, et espérer que le fil interrompu se comportera correctement lors de l'interruption.

ici, j'ai nommé le fil avec la boucle offensante pour une identification plus facile. Attention, la solution suivante est vulnérable aux conditions de course.

    Thread loop = new Thread() { 

        public void run() {
            Thread.currentThread().setName("loop");
            while(true) {
                System.out.print(".");
            }
        }
    }.start();

puis en une autre classe:

    ThreadGroup group = Thread.currentThread().getThreadGroup();
    Thread[] threads = new Thread[group.activeCount()];
    group.enumerate(threads);

    for(Thread t : threads) {
        if(t.getName().equals("loop")) {
            /* Thread.stop() is a horrible thing to use. 
               Use Thread.interrupt() instead if you have 
               any control over the running thread */
            t.stop();
        }
    }

notez que dans mon exemple je suppose que les deux threads sont dans le même ThreadGroup. Il n'y a aucune garantie que ce sera le cas, alors vous pourriez avoir besoin de parcourir plus de groupes.

si vous avez un certain contrôle sur ce, un modèle décent ici serait d'avoir while(!isInterrupted()) à la place dans la déclaration de boucle et d'utiliser t.interrupt() au lieu de t.stop() .

mon seul conseil à vous, même après l'affichage cela, c'est de ne pas le faire. Vous peut le faire, mais vous vraiment ne devrait pas .

6
répondu Joel Westberg 2012-08-17 10:09:48

je pense que ce n'est pas possible. Uniquement en utilisant break dans la boucle. Vous pouvez utiliser

while(cond) {}

et de quelque autre endroit le font false

5
répondu Dmitriy Ugnichenko 2012-08-17 08:38:09

vous pouvez interrompre ce thread en gardant sa référence statique de référence héritée de ce Thread [main] en demandant de Thread.currentThread(), comme ceci

public class LoopInfinite{
public static Thread main = null;
public static void main(String[] args){
    main = Thread.currentThread();
    for(;;)
       System.out.println("Stackoverflow");
    }
}

et pour terminer vous pouvez appeler cela d'un autre fil

LoopInfinite.main.interrupt();

Mais il ne fonctionne que si les deux fils font partie du même groupe. Sinon, appeler thread va obtenir SecurityException

3
répondu Siddharth Tyagi 2012-08-17 09:03:58

vous ne pouvez pas empêcher cela en dehors de cette classe. Si vous utilisez l'héritage, vous pouvez écraser votre boucle, mais sans avorter-flag vous ne pourrez pas le faire.

2
répondu rollstuhlfahrer 2012-08-17 08:36:41

question très ouverte, mais arrêter une telle boucle nécessiterait très probablement que vous opériez à partir d'un autre fil. L'autre thread serait alors nécessaire de définir une variable que votre boucle infinie pouvez vérifier régulièrement, et si la variable a une certaine valeur; sortir de la boucle.

2
répondu Thorbear 2012-08-17 08:38:19

Vous ne serez pas en mesure d'interrompre cette boucle sans arrêter le processus entièrement. En général, si vous essayez de le faire à partir d'une source externe (je suppose que vous n'avez aucun contrôle sur le code source, car si vous le faites, vous pouvez facilement définir une condition dans la boucle, comme un booléen que vous pouvez définir à partir d'un Thread externe), vous devrez arrêter le Thread courant, que vous le fassiez à travers le Thread object (vous devrez trouver une référence à celui-ci d'une manière ou d'une autre, par exemple en passant par fils existants ), ou si vous l'arrêtez comme un processus de système .

une autre option serait de surcharger la méthode avec une boucle qui n'est pas une boucle infinie, mais malheureusement cela ne s'applique pas à votre exemple parce que c'est une méthode statique.

2
répondu Thor84no 2017-05-23 10:31:28

votre type de problème ressemble à un problème de filetage. Mais encore, il est maintenant une bonne pratique d'inclure un drapeau d'arrêt, même dans les fils

2
répondu IvoC 2012-08-17 08:40:22

si vous avez besoin d'une boucle" infinie", vous avez certainement besoin d'un thread (sinon votre application sera bloquée jusqu'à la fin de la boucle).

class BigLoop extends Thread
{

    private boolean _sexyAndAlive = true;

    // make some constructor !

    public void softTerminate()
    {
    _sexyAndAlive = false;
    }


    public void run()
    {
        try
        {
            while( _sexyAndAlive )
            {
               // Put your code here 
            }
        }
        catch( Some Exceptions ... )
        {
            // ...
        }
        // put some ending code here if needed
    }
}


// in another file :

BigLoop worker = new BigLoop();
worker.start(); // starts the thread

// when you want to stop it softly
worker.softTerminate();

donc, c'est une méthode simple pour avoir la boucle de courant de fond.

2
répondu Benj 2012-08-17 09:03:04

ajouter une variable shouldBreak ou quelque chose qui peut être défini en utilisant getter et setter.

public class LoopInfinite {
private boolean shouldBreak = false;

public boolean isShouldBreak() {
    return shouldBreak;
}

public void setShouldBreak(boolean shouldBreak) {
    this.shouldBreak = shouldBreak;
}

public static void main(String[] args) {
    // Below code is just to simulate how it can be done from out side of
    // the class
    LoopInfinite infinite = new LoopInfinite();
    infinite.setShouldBreak(true);
    for (;;) {
        System.out.println("Stackoverflow");
        if (infinite.shouldBreak)
            break;
    }
}

}

1
répondu Amit Deshpande 2012-08-17 08:58:16

voici ce que j'ai fait:

while(Exit == false){
    Scanner input = new Scanner(System.in);
    String in = input.next();

    switch(in){
        case "FindH": 
            FindHyp hyp = new FindHyp();
            float output = hyp.findhyp();
            System.out.println(output); 
        case "Exit":
            Exit = true;
    break;

    }
  }  
0
répondu Confederate 3320 2016-10-21 01:14:26