Cómo interrumpir un Bucle Infinito


Aunque sé que va a ser un poco tonto preguntar, todavía quiero preguntar más sobre la perspectiva técnica de la misma.

Un ejemplo simple de un bucle infinito:

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

¿Cómo puedo interrumpir (detener) este bucle infinito desde fuera de esta clase (por ejemplo, con la ayuda de la herencia)?

Author: Boann, 2012-08-17

12 answers

Me siento sucio incluso escribiendo esto, pero...

Desde un subproceso diferente, puedes llamar a System.setOut() con una implementación PrintStream, que lanza un RuntimeException cuando llamas a println().

 49
Author: David Grant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 11:45:20

Podemos lograrlo usando la variable volatile, que cambiaremos ouside Thread y detendremos el bucle.

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

Esta es la mejor manera de escribir Bucle infinito.

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
Author: Subhrajyoti Majumder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-12 15:35:25

Usted puede obtener el hilo que ejecuta el bucle infinito desde un hilo diferente y llamar a la interrupción en él. Sin embargo, tendrás que estar muy seguro de lo que estás haciendo, y esperar que el hilo interrumpido se comporte correctamente cuando se interrumpa.

Aquí, he nombrado el hilo con el bucle ofensivo para una identificación más fácil. Tenga en cuenta que la siguiente solución es vulnerable a las condiciones de carrera.

    Thread loop = new Thread() { 

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

Luego en alguna otra clase:

    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();
        }
    }

Tenga en cuenta que en mi ejemplo supongamos que los dos hilos están en el mismo grupo de hilos. No hay garantía de que este sea el caso, por lo que es posible que tenga que atravesar más grupos.

Si tiene algún control sobre esto, un patrón decente aquí sería tener while(!isInterrupted()) en su lugar en la declaración de bucle y usar t.interrupt() en lugar de t.stop().

Mi único consejo para ti, incluso después de publicar esto, es que no hagas esto. Tú puedeshacerlo, pero realmente no deberías.

 6
Author: Joel Westberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 10:09:48

Creo que esto no es posible. Solo usando break dentro del bucle. Usted podría utilizar

while(cond) {}

Y de algún otro lugar hacerlo falso

 5
Author: Dmitriy Ugnichenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 08:38:09

Puede interrumpir este subproceso manteniendo su referencia estática de referencia heredada a este Subproceso [main] preguntando a Thread.currentThread(), como esto

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

Y para terminar puede llamar a esto desde algún otro hilo

LoopInfinite.main.interrupt();

Pero solo funcionará si ambos hilos son parte del mismo grupo. De lo contrario, llamar al hilo obtendrá SecurityException

 3
Author: Siddharth Tyagi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 09:03:58

No se puede detener esto desde fuera de esta clase. Si usa herencia puede sobrescribir su bucle, pero sin abort-flag no podrá hacerlo.

 2
Author: rollstuhlfahrer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 08:36:41

Pregunta muy abierta, pero detener tal bucle probablemente requeriría que operes desde otro hilo. El otro hilo entonces tendría que establecer alguna variable que su bucle infinito puede comprobar regularmente, y si la variable tiene un cierto valor; romper el bucle.

 2
Author: Thorbear,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 08:38:19

No podrá interrumpir este bucle en particular sin detener el proceso por completo. En general, si estás tratando de hacerlo desde una fuente externa (asumo que no tienes control sobre el código fuente, porque si lo hicieras podrías establecer fácilmente una condición en el bucle, como un booleano que podrías establecer desde un Hilo externo), tendrás que detener el Hilo en ejecución, ya sea que lo hagas a través del objeto Thread (tendrás que encontrar una referencia a él de alguna manera, por ejemplo looping through existing Threads), o si lo detiene como un proceso del sistema .

Otra opción sería anular el método con un bucle que no es un bucle infinito, pero desafortunadamente eso no se aplica a su ejemplo porque es un método estático.

 2
Author: Thor84no,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:28

Su tipo de problema se parece a un problema de enhebrado. Pero aún así, ahora es una buena práctica incluir una bandera de detención incluso en hilos

 2
Author: IvoC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 08:40:22

Si necesita un bucle "infinito", seguramente necesita un hilo (de lo contrario, su aplicación se atascará hasta el final del bucle).

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();

Por lo tanto, este es un método simple para tener un bucle en segundo plano.

 2
Author: Benj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 09:03:04

Agregue una variable shouldBreak o algo que se pueda establecer usando getter y 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
Author: Amit Deshpande,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 08:58:16

Esto es lo que hice:

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
Author: Confederate 3320,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-21 01:14:26