如何中断无限循环

时间:2022-07-02 08:40:56

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)?

如何从这个类的外部中断(停止)这个无限循环(例如,在继承的帮助下)?

12 个解决方案

#1


49  

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

在不同的线程中,您可以使用PrintStream实现调用System.setOut(),该实现在调用println()时会抛出RuntimeException。

#2


26  

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

我们可以使用volatile变量来实现它,我们将改变ouside Thread并停止循环。

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

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("*");
             }
      }
      public void cancel(){
        cancelled=true;
      }
}

#3


6  

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.

请注意,在我的示例中,我假设两个线程在同一个ThreadGroup中。不能保证会出现这种情况,因此您可能需要遍历更多组。

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

如果你对此有一些控制权,那么这里一个合适的模式就是在循环声明中使用while(!isInterrupted())并使用t.interrupt()而不是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


5  

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

我认为这是不可能的。仅在循环内使用break。你可以用

while(cond) {}

And from some other place make it false

从其他地方来说,这是假的

#5


3  

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

您可以通过向Thread.currentThread()询问,保持其对此Thread [main]的继承引用的静态引用来中断此线程,就像这样

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

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

但只有当两个线程都属于同一组时,它才会起作用。否则调用线程将获得SecurityException

#6


2  

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.

你无法阻止这个课程以外的课程。如果你使用继承,你可以覆盖你的循环,但没有abort-flag,你将无法这样做。

#7


2  

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


2  

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.

如果不完全停止进程,您将无法中断此特定循环。一般来说,如果你试图从外部源代码(我假设你无法控制源代码,因为如果你这样做,你可以轻松地在循环中设置一个条件,比如你可以设置一个布尔值从外部线程),您将不得不暂停正在运行的线程,无论您是通过Thread对象执行此操作(您必须以某种方式找到对它的引用,例如通过循环现有的线程),或者是否停止它作为一个系统过程。

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


2  

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


2  

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


1  

Add a variable shouldBreak or something which can be set using getter and setter.

添加变量shouldBreak或可以使用getter和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("*");
        if (infinite.shouldBreak)
            break;
    }
}

}

}

#12


0  

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;

    }
  }  

#1


49  

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

在不同的线程中,您可以使用PrintStream实现调用System.setOut(),该实现在调用println()时会抛出RuntimeException。

#2


26  

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

我们可以使用volatile变量来实现它,我们将改变ouside Thread并停止循环。

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

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("*");
             }
      }
      public void cancel(){
        cancelled=true;
      }
}

#3


6  

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.

请注意,在我的示例中,我假设两个线程在同一个ThreadGroup中。不能保证会出现这种情况,因此您可能需要遍历更多组。

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

如果你对此有一些控制权,那么这里一个合适的模式就是在循环声明中使用while(!isInterrupted())并使用t.interrupt()而不是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


5  

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

我认为这是不可能的。仅在循环内使用break。你可以用

while(cond) {}

And from some other place make it false

从其他地方来说,这是假的

#5


3  

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

您可以通过向Thread.currentThread()询问,保持其对此Thread [main]的继承引用的静态引用来中断此线程,就像这样

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

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

但只有当两个线程都属于同一组时,它才会起作用。否则调用线程将获得SecurityException

#6


2  

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.

你无法阻止这个课程以外的课程。如果你使用继承,你可以覆盖你的循环,但没有abort-flag,你将无法这样做。

#7


2  

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


2  

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.

如果不完全停止进程,您将无法中断此特定循环。一般来说,如果你试图从外部源代码(我假设你无法控制源代码,因为如果你这样做,你可以轻松地在循环中设置一个条件,比如你可以设置一个布尔值从外部线程),您将不得不暂停正在运行的线程,无论您是通过Thread对象执行此操作(您必须以某种方式找到对它的引用,例如通过循环现有的线程),或者是否停止它作为一个系统过程。

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


2  

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


2  

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


1  

Add a variable shouldBreak or something which can be set using getter and setter.

添加变量shouldBreak或可以使用getter和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("*");
        if (infinite.shouldBreak)
            break;
    }
}

}

}

#12


0  

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;

    }
  }