24

虽然我知道问起来有点傻,但我还是想多问问它的技术角度。

一个简单的无限循环示例:

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

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

4

12 回答 12

49

写到这里我都觉得很脏,但是...

从不同的线程,你可以调用System.setOut()一个PrintStream实现,RuntimeException当你调用println().

于 2012-08-17T08:41:24.553 回答
26

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

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

这是编写无限循环的更好方法。

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;
      }
}
于 2012-08-17T08:41:09.573 回答
6

可以从另一个线程获取运行无限循环的线程并在其上调用中断。不过,您必须非常确定自己在做什么,并希望被中断的线程在中断时能够正常运行。

在这里,我用有问题的循环命名了线程,以便于识别。请注意,以下解决方案容易受到竞争条件的影响。

    Thread loop = new Thread() { 

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

然后在其他课程中:

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

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

如果您对此有一些控制权,那么这里的一个不错的模式是while(!isInterrupted())在循环声明中使用t.interrupt()而不是使用t.stop().

我给你的唯一建议是,即使在发布后,也不要这样做。你可以这样做,但你真的不应该

于 2012-08-17T08:57:28.677 回答
5

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

while(cond) {}

并从其他地方使它成为

于 2012-08-17T08:38:09.170 回答
3

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

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

要终止,您可以从其他线程调用它

LoopInfinite.main.interrupt();

但它只有在两个线程都属于同一组时才有效。否则调用线程会得到SecurityException

于 2012-08-17T09:03:58.903 回答
2

你的问题看起来像一个线程问题。但是,即使在线程中包含停止标志,现在也是一个好习惯

于 2012-08-17T08:40:22.743 回答
2

你不能从这个类之外阻止它。如果您使用继承,您可以覆盖您的循环,但如果没有 abort-flag,您将无法这样做。

于 2012-08-17T08:36:41.543 回答
2

非常开放的问题,但停止这样的循环很可能需要您从另一个线程进行操作。然后另一个线程需要设置一些你的无限循环可以定期检查的变量,如果该变量具有某个值;跳出循环。

于 2012-08-17T08:38:19.433 回答
2

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

另一种选择是使用不是无限循环的循环覆盖该方法,但不幸的是,这不适用于您的示例,因为它是一个静态方法。

于 2012-08-17T08:39:24.367 回答
2

如果你需要一个“无限”循环,你肯定需要一个线程(否则你的应用程序将被卡住直到循环结束)。

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

因此,这是一种让后台运行循环的简单方法。

于 2012-08-17T09:03:04.520 回答
1

添加一个变量 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("Stackoverflow");
        if (infinite.shouldBreak)
            break;
    }
}

}

于 2012-08-17T08:58:16.093 回答
0

这是我所做的:

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;

    }
  }  
于 2016-10-21T01:14:26.193 回答