2010-11-19 9 views
2

Ich schreibe ein Testsystem und ich möchte nur zählen, wie viele Sekunden der Benutzer für diese Frage ausgegeben hat. d. h. ich drucke die Frage (Standard System.out.println), warte dann 5 Sekunden und wenn innerhalb dieser 5 Sekunden der Benutzer antwortet (über die Standardeingabe), möchte ich diesen Wert behalten. Wenn der Benutzer innerhalb von 5 Sekunden keine Antwort erhalten hat, muss er diese Frage überspringen und fortfahren. Das Problem ist - ich lese Benutzerantworten über Scanner-Objekt, und etwas wie in.nextInt() ist unkontrollierbar, nehme ich an.Empfange Eingang in bestimmter Zeit

Wie kann ich dieses Problem lösen? Hier ist ein Fragment meines Codes ohne diese Funktionalität. Kannst du mir einige Hinweise geben, was ich hinzufügen soll?

public void start() { 
    questions.prepareQuestions(numQuestions); 
    Scanner in=new Scanner(System.in); 
    boolean playerIsRight=false,botIsRight=false; 
    int playerScore=0,botScore=0; 
    for (int i = 0; i < numQuestions; i++) { 
     questions.askQuestion(i); 
     System.out.print("Your answer(number): "); 
     playerIsRight=questions.checkAnswer(i,in.nextInt()-1); //in.nextInt() contains the answer 
     botIsRight=botAnswersCorrectly(i + 1); 
     if(playerIsRight){ playerScore++; System.out.println("Correct!");} 
     else System.out.println("Incorrect!"); 
     if(botIsRight) botScore++; 
     System.out.print("\n"); 
    } 
    if(botScore>playerScore) System.out.println("Machine won! Hail to the almighty transistors!"); 
    else if(playerScore>botScore) System.out.println("Human won! Hail to the power of nature!"); 
    else System.out.println("Tie. No one ever wins. No one finally loses."); 
} 

Antwort

1

Ich würde in diesem Fall zwei Threads verwenden. Der Hauptthread schreibt Fragen, wartet auf Antworten und hält Punkte. Ein untergeordneter Thread liest die Standardeingabe und sendet die Antworten an den Hauptthread, möglicherweise über eine BlockingQueue.

unter Verwendung des poll() Verfahren auf der Sperr Warteschlange fünf Sekunden lang auf eine Antwort zu warten, bis das Hauptthread kann:

… 
BlockingQueue<Integer> answers = new SynchronousQueue(); 
Thread t = new ReaderThread(answers); 
t.start(); 
for (int i = 0; i < numQuestions; ++i) { 
    questions.askQuestion(i); 
    System.out.print("Your answer (number): "); 
    Integer answer = answers.poll(5, TimeUnit.SECONDS); 
    playerIsRight = (answer != null) && questions.checkAnswer(i, answer - 1); 
    … 
} 
t.interrupt(); 

Wenn dieser Aufruf null zurückkehrt, weiß der Haupt-Thread, dass der Faden Kind nicht erhalten hat jede Eingabe während dieser Zeit, und kann die Punktzahl entsprechend aktualisieren und die nächste Frage ausdrucken.

Die ReaderThread würde wie folgt aussehen:

class ReaderThread extends Thread { 

    private final BlockingQueue<Integer> answers; 

    ReaderThread(BlockingQueue<Integer> answers) { 
    this.answers = answers; 
    } 

    @Override 
    public void run() { 
    Scanner in = new Scanner(System.in); 
    while (!Thread.interrupted()) 
     answers.add(in.nextInt()); 
    } 

} 

auf System.in Verwendet wird die Scanner blockieren, bis der Benutzer Enter drückt, so ist es, dass der Benutzer einen Text eingegeben hat passieren könnte, aber noch nicht gedrückt Enter wenn Der Haupt-Thread läuft ab und geht zur nächsten Frage über. Der Benutzer müsste seinen ausstehenden Eintrag löschen und eine neue Antwort für die neue Frage eingeben. Ich kenne keinen sauberen Weg um diese Peinlichkeit herum, da es keinen zuverlässigen Weg gibt, den Anruf zu unterbrechen.

+0

Es kann lahm sein, aber was ist, wenn ich einen neuen Thread nach dem Stellen einer Frage, Anruf warten (Timeout) und in neuen Thread ich werde auf die Antwort warten und nach dem Empfang, ich werde notify() auf Objekt in aufrufen Elternteil-Thread Wird es funktionieren? – Anton

+0

Ich habe gerade überprüft - es funktioniert nicht :) – Anton

+0

Sie könnten Ihre eigene Lösung mit 'warten' und' notify' rollen, aber wie Sie gesehen haben, ist es schwierig, es richtig zu machen. Die Verwendung einer 'BlockingQueue' ist ungefähr gleichwertig, aber sie ist in einem sauberen, zuverlässigen Paket enthalten. – erickson

Verwandte Themen