Подтвердить что ты не робот

Как прерывать бесконечную петлю

Хотя я знаю, что будет немного глупо спрашивать, но я хочу узнать больше о технической перспективе.

Простой пример бесконечного цикла:

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

Как я могу прерывать (останавливать) этот бесконечный цикл извне этого класса (например, с помощью наследования)?

4b9b3361

Ответ 1

Я чувствую себя грязным, даже пишу это, но...

В другом потоке вы можете вызвать System.setOut() с реализацией PrintStream, которая выдает RuntimeException при вызове println().

Ответ 2

Мы можем достичь этого с помощью переменной volatile, которую мы изменим ouside 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;
      }
}

Ответ 3

Вы можете получить поток, выполняющий бесконечный цикл из другого потока, и вызвать прерывание на нем. Вы должны быть очень уверены в том, что делаете, и надеяться, что прерванный поток будет корректно вести себя при прерванной работе.

Здесь я назвал поток с оскорбительным циклом для упрощения идентификации. Помните, что следующее решение уязвимо для условий гонки.

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

Мой единственный совет для вас, даже после публикации этого, заключается в том, чтобы не делать этого. Вы можете сделать это, но вы действительно не должны.

Ответ 4

Я думаю, что это невозможно. Только использование прерывания в цикле. Вы можете использовать

while(cond) {}

И из другого места сделайте его ложным

Ответ 5

Вы можете прервать этот поток, сохранив его статическую ссылку унаследованной ссылки на этот Thread [main], запросив у Thread.currentThread(), как этот

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

Ответ 6

Вы не можете остановить это из-за пределов этого класса. Если вы используете наследование, вы можете перезаписать свой цикл, но без флага прерывания вы не сможете этого сделать.

Ответ 7

Очень открытый вопрос, но остановка такого цикла, скорее всего, потребует от вас работы из другого потока. Затем другой поток должен был установить некоторую переменную, которую ваш бесконечный цикл может проверять регулярно, и если переменная имеет определенное значение; вырваться из цикла.

Ответ 8

Вы не сможете прервать этот конкретный цикл, не прекратив полностью процесс. В общем, если вы пытаетесь сделать это из внешнего источника (я предполагаю, что у вас нет контроля над исходным кодом, потому что если бы вы это сделали, вы могли бы легко установить условие в цикле, например логическое значение, которое вы могли бы установить из внешнего потока), вам придется остановить текущий поток, независимо от того, выполняете ли вы это через объект Thread (вам нужно как-то найти ссылку на него, например, путем перехода через существующие темы), или остановите его как системный процесс .

Другой вариант заключается в переопределении метода с циклом, который не является бесконечным циклом, но, к сожалению, это не относится к вашему примеру, потому что это статический метод.

Ответ 9

Ваша проблема выглядит как проблема Threading. Но, тем не менее, теперь хорошей практикой является включение флаг остановки даже в потоки

Ответ 10

Если вам нужен "бесконечный" цикл, вам обязательно нужен поток (иначе ваше приложение будет застревать до конца цикла).

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

Итак, это простой метод для выполнения фонового цикла.

Ответ 11

Добавьте переменную mustBreak или что-то, что можно установить с помощью 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;
    }
}

}

Ответ 12

Вот что я сделал:

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;

    }
  }