externally ending infinite loop java

439 views Asked by At

I'm writing a program that will mark an algorithm submitted by a group of students. I plan on copying their algorithm method into the program and running it to see the results; however, it is required that the algorithm not run for more than 10 seconds.

I constructed a ExecutorService to end the algorithm which works for the userInput algorithm (commented out) but did not work for an infinite loop.

From what I know about threads, interrupting it would require altering the algorithm (add a flag), and stopping a thread is depreciated, so is there any other way to end the infinite loop without altering the algorithm in anyway?

Here's the code:

public class TestAlgo{
private String move;

public static void main(String[] args){
    TestAlgo testAlgo = new TestAlgo();
    testAlgo.runGame();
}

public void runGame(){
    Cram game = new Cram();
    boolean start = game.startGame();


    while (start){
        ExecutorService executor = Executors.newSingleThreadExecutor();/////
        Future<String> future = executor.submit(new Task());/////
        move = "";
        try {
            System.out.println("Started..");
            move = future.get(10, TimeUnit.SECONDS);
            System.out.println("Finished!");
        } catch (TimeoutException e) {
            future.cancel(true);
            move = "Timeout";
            System.out.println("Terminated!");
        } catch (InterruptedException ie){
            System.out.println("Error: InterruptedException");
        } catch (ExecutionException ee){
            System.out.println("Error: ExecutionException");
        }
        System.out.println("Move: " + move);
        executor.shutdownNow();



        if (game.sendMove(move)) break;
        game.printBoard();
        if (game.getMove()) break;
        game.printBoard();
    }
}

// public static String algorithm(){
//     while (true){ //infinite loop
//         System.out.println("Algo is running...");
//     }
//     return "test";
// }

public static String algorithm(){
    Scanner userInputScanner = new Scanner(System.in);
    System.out.print("Please enter your move: ");
    String input = userInputScanner.nextLine();
    return input;
}}

class Task implements Callable<String> {
@Override
public String call() throws Exception {
    String move = TestAlgo.algorithm();
    return move;
}}
3

There are 3 answers

0
DoubleA On BEST ANSWER

Google Guava's SimpleTimeLimiter should help. Simply wrap your ExecutorService within the SimpleTimeLimiter, and then use the callWithTimeout method to specify a given timeout period; handle the UncheckedTimeoutException to indicate that the timeout was reached. Finally, call the shutdown method of the ExecutorService that was wrapped in the SimpleTimeLimiter.

1
Alex S. Diaz On

You could finish your thread in the while loop:

public static String algorithm(){
    long start = System.currentTimeMillis();
    long end = start + 10*1000; // 10 seconds?
    while (System.currentTimeMillis() < end){ //not-so-infinite loop
         System.out.println("Algo is running...");
    }
    return "test";
}

But if you don't want to modify the algorithm() method, you could check this, or this.

0
Patricia Shanahan On

As an alternative to running the untrusted code in a thread in your JVM, consider firing off a separate process using ProcessBuilder. You can then use the Process destroyForcibly method to terminate it.