There are many threads on SO about interrupting reading the system.in but what I am looking for here is some kind of advice as to how to best code what I am trying to achieve.
I have a getlogin() method that needs to do the following: ask a user to input the desired login environnement details, if after 6 seconds user have not input a valid value (“live” or “test”) then set userlogin variable to “test” and return it to the caller.
I have taken the following approach for the getlogin() implementation:
-
launch two threads which do the following:
thread1creates a scanner object then callsscanner.nextline()and depending on user input set a variableuserlogin. Interrupts thread2 before exitingthread1.thread2waits 6 seconds and if after thatuserloginis still not set, then set a default value foruserlogin. Interruptsthread1before exitingthread2.
-
join
thread2to stop mainThreadfrom returninguserloginas null -
return userlogin
The problem I have with the approach is that scanner.nextline() does not interrupt when thread2 calls thread1.interrupt, which is why I do not join thread1 in step 2 as the main Thread would hang.
Is there a way to get thread1 to complete after thread2 interrupts it? Or else is this approach completely overkill and there is a much simpler way to achieve the contract?
The simplest solution is to expose the underlying stream in the “reading” thread and close that stream from the timeout thread. This should interrupt the reading and raise an exception. Handle this exception and you should be able to proceed with your logic. The only gotcha is that you won’t be able to re-use the same stream again. Unfortunately there is no easy way to deal with interruption of blocking system calls.
EDIT:
Following a completely different line of reasoning; given that we can’t close the input stream just to interrupt it, the only way I can think of is to use the “programmatic user input” facilities offered by the Robot class. Here is an example which works out for me:
The above code uses the logic that once that timeout has expired, we simulate a newline which will cause the “name” variable to be blank. Then we have a check which performs the necessary logic and sets the appropriate user name.
The gotcha about the above approach is that it:
ENTERkey-press will be registered for that window as opposed to your application window.Hope this helps you out. I’m really out of ideas now. 🙂