Search code examples
javatimerexceptiontimeoutexception

Timer issues in java when using Timeout Exceptions, code doesn't run correctly after a Timeout Exception


I'm designing a game in java called that's similar to the board game go. In the implementation there is also a mode called speed mode, where if a player doesn't take a turn within the time limit (5 seconds) the other player is to win. This mode can also be won normally be "capturing" the opposition piece. After either of these conditions is met , the game is to be ran again from the main menu. This works fine in normal mode and in speed mode when the win conditions are met by capturing. When it's won by time running out however it behaves very oddly, almost randomly prompting for input and printing.

The code for the time is as follows:

        public Boolean speedMode(Player player, Player opponent) {
            ExecutorService service = Executors.newSingleThreadExecutor();
            try {
                Runnable r = new Runnable() {
                    Boolean outOfRange;
                    public void run() {
                        do {
                            outOfRange = takeTurn(player);
                        } while (outOfRange == true);

                    }
                };
                Future<?> f = service.submit(r);
                f.get(5, TimeUnit.SECONDS);
            } catch (final InterruptedException e) {
                System.out.println("The thread was interrupted during sleep, wait or join");
            } catch (final TimeoutException e) {
                player.setWon(false);
                System.out.println("\n" + player.getName() +", you took too long... ");
                return true;
            } catch (final ExecutionException e) {
                System.out.println("An exception from within the Runnable task");
            }

            return false;
        }

When the TimeoutException happens the oppisite player wins while loop shown beow is exited and the correct congratulations are printed. The problem is when It starts the new game at the bottom line of code thats when the weird behaviour starts. Is there something I need to close perhaps in the timer method?It's almost like it's still running in the back ground.

else {

                do {
                    timeOut = speedMode(second, first);

                    if(winCheck1(first) == true || timeOut == true){
                        break;
                    }

                    timeOut = speedMode(first, second);

                } while (winCheck1(second) != true && timeOut != true);

                if(player1.isWon() == true){
                    System.out.println("\n\nCongratulations " + player1.getName() + " you are the winner!\n\n");
                }

                else{
                    System.out.println("\n\nCongratulations " + player2.getName() + " you are the winner!\n\n");
                }

            }

            //reload the menu
            Game game = new Game();
        }

Basically my question is; can anyone tell me why starting a new game does not work correctly after throwing a TimeoutException?


Solution

  • Is there something I need to close perhaps in the timer method?It's almost like it's still running in the back ground.

    If you don't call shutdown on the executor the worker thread that the executor created will hang around. (This is independent of the scope in which you declared the executor.) If it is a non-daemon thread then it will keep the old JVM alive.

    Also your task needs to be responsive to interruption. See the documentation for shutdownNow:

    There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.

    "Responding to interrupts" means checking Thread.currentThread().isInterrupted() to see if the thread has been canceled and then acting on it (finding a stopping place, doing cleanup, and exiting the run method), and restoring the interrupted flag (Thread.currentThread().interrupt()) if an InterruptedException or InterruptedIOException is caught.