How to interrupt an Infinite Loop

2019-03-10 20:52发布

问题:

Though I know it'll be a bit silly to ask, still I want to inquire more about the technical perspective of it.

A simple example of an infinite loop:

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

How can I interrupt (stop) this infinite loop from outside of this class (e.g., with the help of inheritance)?

回答1:

I feel dirty even writing this, but...

From a different thread, you could call System.setOut() with a PrintStream implementation, which throws a RuntimeException when you call println().



回答2:

We can achieve it using volatile variable, which we will change ouside Thread and stop the loop.

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

This is better way to write Infinite Loop.

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


回答3:

You can get at the thread running the infinite loop from a different thread and call interrupt on it. You'll have to be very sure what you are doing though, and hope that the interrupted thread will behave properly when interrupted.

Here, I've named the thread with the offending loop for easier identification. Beware that the following solution is vulnerable to race conditions.

    Thread loop = new Thread() { 

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

Then in some other class:

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

Note that in my example I assume the two threads are in the same ThreadGroup. There is no guarantee that this will be the case, so you might need to traverse more groups.

If you have some control over this, a decent pattern here would be to have while(!isInterrupted()) instead in the loop declaration and use t.interrupt() instead of t.stop().

My only advice to you, even after posting this, is to not do this. You can do it, but you really shouldn't.



回答4:

I think this is not possible. Only using break within the loop. You could use

while(cond) {}

And from some other place make it false



回答5:

You can interrupt this thread by keeping its static reference of inherited reference to this Thread [main] by asking from Thread.currentThread(), like this

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

And to terminate you can call this from some other thread

LoopInfinite.main.interrupt();

But it will only work if both threads are part of the same group. Otherwise calling thread will get SecurityException



回答6:

You cannot stop this from outside of this class. If you use inheritance you can overwrite your loop, but without abort-flag you won't be able to do so.



回答7:

Very open question, but stopping such loop would most likely require you to operate from another thread. The other thread would then need to set some variable that your infinite loop can check regularly, and if the variable has a certain value; break out of the loop.



回答8:

You won't be able to interrupt this particular loop without halting the process entirely. In general, if you're trying to do it from an external source (I'm assuming you have no control over the source code, because if you did you could easily set a condition in the loop, such as a boolean you could set from an external Thread), you will have to halt the running Thread, whether you do this through the Thread object (you'll have to find a reference to it somehow, for example by looping through existing Threads), or whether you halt it as a system process.

Another option would be to override the method with a loop that isn't an infinite loop, but unfortunately that doesn't apply to your example because it's a static method.



回答9:

Your kind of problem looks like a Threading problem. But still, it is now a a good practice to include a stopping flag even in threads



回答10:

If you need an "infinite" loop, you sure need a thread (else your app will be stuck until the end of the loop).

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

So, this is a simple method to have background running loop.



回答11:

Add a variable shouldBreak or something which can be set using getter and 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;
    }
}

}



回答12:

Here is what I did:

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;

    }
  }