I\'m writing a testing system and i all i want to do is to count how many seconds had user spent on this question. i.e. i print question(standard System.out.println), then wait
I would use two threads in this case. The main thread writes questions, waits for answers, and keeps score. A child thread reads standard input and sends the answers to the main thread, perhaps via a BlockingQueue.
The main thread can wait for five seconds for an answer by using the poll()
method on the blocking queue:
…
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();
If this call returns null
, the main thread knows that the child thread didn't receive any input during that time, and can update the score appropriately and print the next question.
The ReaderThread
would look something like this:
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());
}
}
Used on System.in
, the Scanner
will block until the user presses Enter
, so it might happen that the user has entered some text but not yet pressed Enter
when the main thread times out and moves on to the next question. The user would have to delete their pending entry and enter a new answer for the new question. I don't know of a clean way around this awkwardness, since there's not a reliable way to interrupt the nextInt()
call.