简体   繁体   English

Java:如何在使用 Executorservice 和 future for timer 时中断循环?

[英]Java: How to break loop when using Executorservice and future for timer?

I'm trying to make a timer for a simple math quiz where user needs to answer the question within 10 seconds, and when that time exceeds, it will load to the next question.我正在尝试为一个简单的数学测验制作一个计时器,用户需要在 10 秒内回答问题,当超过该时间时,它将加载到下一个问题。 I found the solution to implement Executorservice and future, but I'm having a problem when it keeps repeating the loop for invalid input (numberformat exception) when user enter other input than integers at my Game class.我找到了实现 Executorservice 和 future 的解决方案,但是当用户在我的 Game 类中输入除整数以外的其他输入时,它不断重复循环以获取无效输入(数字格式异常)时遇到问题。

Hope this is useful to know: class MathQuestion (where the math questions are generated), Game (the game round initiated), and GameTimer.希望这对了解有用:类 MathQuestion(生成数学问题的地方)、Game(开始的游戏回合)和 GameTimer。

Game class :-游戏类:-

  //for 10 rounds of game
   for (int i=0; i<rounds; ++i)
   {
       System.out.println("*************************************");
       System.out.println("\nRound " + (i+1)
               + "\nEnter 'x' to quit game");

       System.out.println("\nQuestion:");
      //call method to generate question and get correct answer
      result = quiz.Questions();
      System.out.println("You have 10 seconds");

     //to make sure we read a line or interrupt it for the timer
     ExecutorService ex = Executors.newSingleThreadExecutor();
      try
     {
     //retrieve the actual result at a later point in time.
     Future<String> ans = ex.submit(new GameTimer());
     try {

      boolean validInput = false;

      do
      {

           System.out.println("\nEnter your answer: ");//prompt user input answer
          //10 secs wait to obtain result from player
          //wait until callable complete before return result
            answer = ans.get(10, TimeUnit.SECONDS);
           //answer = scan.nextLine();
           try
           {
               //valid player input
               pAnswer = Double.parseDouble(answer.trim()) ; //convert to double
               validInput = true;

           }catch (NumberFormatException e){ //other input other than integers *this the repeated loop  
            System.out.println("Invalid input. Please try again.");
            validInput = false;
            ans = ex.submit(new GameTimer()); //resubmit task solution
            }

           if (answer.trim().equalsIgnoreCase("x")) //player quit game
           {
               quit=true;
               break;
           }

      }while (!validInput);
    if (quit)
    {
     break;
    }
            //for correct answer
            if (Math.abs(Double.parseDouble(answer) - quiz.answer)  <= 0.01) {
            //add 10 points
            this.gamer.setScore(score+=10); 
            System.out.println("You got it right!");
        } 
        else //wrong answwer
        {
            //subtract 10 points
            this.gamer.setScore(score-=10);;
            System.out.println("You got it wrong!");

        }
        } catch (InterruptedException ex1) {
            Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (ExecutionException ex1) {
            Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex1);
        } catch (TimeoutException ex1) {
            System.out.println ("\nTime's up! Better luck next time~");
        }
    }finally {
      ex.shutdownNow(); //stop all running tasks and shut the executor down immediately.
    }

    }     

GameTimer class :- GameTimer 类:-

public class GameTimer implements Callable<String>  {


public String call() throws IOException {
BufferedReader inp = new BufferedReader(new InputStreamReader(System.in));
String input = "";
while ("".equals(input)) {
  try {
    while (!inp.ready()) {
      Thread.sleep(1000);
    }
    input = inp.readLine();
  } catch (InterruptedException e) {
    return null;
  }
} 
return input;
}
}

Here is a picture of the output loop problem: loop problem这是输出循环问题的图片:循环问题

I have been trying to find solutions for timer a really long while now, I would really appreciate it if anyone could help.很长一段时间以来,我一直在努力为计时器寻找解决方案,如果有人能提供帮助,我将不胜感激。 Thank you so much.非常感谢。

*additional : Is there a way to display that timer countdown (eg: 10 9 8..) but with erasing the previous second when the new second count comes up? *附加:有没有办法显示该计时器倒计时(例如:10 9 8 ..)但在新的秒数出现时擦除前一秒?

(without erasing suggestion would also help, thank you! ) (不擦除建议也有帮助,谢谢!)

You cannot keep re-calling get.你不能一直重新调用 get。 Your task is an executable, you submit it and it gets run.您的任务是一个可执行文件,您提交它并运行。 You call .get and it gets the result of your execution.您调用 .get 并获取执行结果。 You need to re-submit the task, for example:您需要重新提交任务,例如:

catch (NumberFormatException e){ //other input other than integers *this the repeated loop  
    System.out.println("Invalid input. Please try again.");
    validInput = false;
    ans = ex.submit(new GameTimer());
}

You might want to keep track of the time elapsed since each time you call get you're using the same timeout.您可能希望跟踪自从每次调用 get 时都使用相同的超时时间以来经过的时间。

In my opinion, you should put the error handling in your callable.在我看来,你应该把错误处理放在你的可调用文件中。

final String question = "Enter double value";
Callable<Double> getDouble = ()-{

     BufferedReader inp = new BufferedReader(neww InputStreamReader(System.in));
     while (!Thread.currentThread().isInterupted()) {
         System.out.println(question);
         try {
             String input = inp.readLine();
             Double v = Double.parseDouble(v);
             return v;
         } catch(Exception e){
             if( Thread.currentThread().isInterrupted()){
                 return null;
             }
             System.out.println("Invalid Input, try again");
         }
     } 

}

Now when you submit the task, you don't have to worry about an invalid double because it is handled in the callable task.现在,当您提交任务时,您不必担心无效的 double,因为它是在可调用任务中处理的。

Future<Double> ans = ex.submit(getDouble);
Double v = ans.get(10, TimeUnit.SECONDS);

This will leave one problem: the task, even if canceled will still be waiting on the standard input.这会留下一个问题:任务即使被取消仍会等待标准输入。 The easiest way to fix this is to tell your user to press enter to continue.解决此问题的最简单方法是告诉您的用户按 Enter 继续。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM