I've been practicing with threads, so I wrote up this timed game where the user needs to guess the correct number (ranges from 1-10). If the user guesses the correct answer in the time limit, the thread stops and the program terminates. It fails to work when the user fails to guess within the time limit. Even though it enters the if-statement after the time limit, it still fails to interrupt the thread completely unless I guess the correct number. I have read other threads but they seem to use ask about the "traditional" guessing game or utilizing Timer. Explanation and/or tips for a suggested solution is also appreciated.
import java.util.*;
import static java.lang.System.out;
import java.io.*;
public class Threading implements Runnable {
private static int num;
private static int k;
public void run() {
try {
Scanner line = new Scanner(System.in);
k = -1;
out.println("Guess!");
while (k != num) {
k = line.nextInt();
if (k != num) {
out.println("Nope");
}
}
}
catch (Exception e) {
out.println("I'm not done!");
}
}
public static void main(String args[]) throws InterruptedException {
num = (int) (Math.random() * 9 + 1);
out.println(num);
Thread t = new Thread(new Threading());
t.start();
long patience = 1000 * 5;
long startTime = System.currentTimeMillis();
while (t.isAlive()) {
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience) && t.isAlive()) {
out.println("I'm in here!");
t.interrupt();
t.join();
out.println("Times up!");
}
}
}
}
Since one of the comments already points out that the call to nextInt will block I don't think there is a need to go into the details of that.
So for now I'm going to assume you're fine with allowing the user 1 final guess after the timer expires.
The following is the modified code including my comments. I refer to the thread you named t as the "guessing thread".
private static int num;
private static int k;
//Changed variable "line" to "scanner" and made it static so that the
// main method can close it once everything is done.
private static Scanner scanner = new Scanner(System.in);
public void run() {
try {
k = -1;
System.out.println("Guess!");
while (k!=num) {
//Added a check for interrupt, otherwise this thread will never
// end unless the user enters the correct answer.
if(Thread.currentThread().isInterrupted())
return;
k = scanner.nextInt();
if(k != num){
System.out.println("Nope");
}
}
System.out.println("Correct!");
} catch (Exception e) {
System.out.println("I'm not done!");
}
}
public static void main(String args[]) throws InterruptedException {
num = (int) (Math.random() * 9 + 1);
System.out.println(num);
//Declared the guessing thread as final so it can be used inside of
// the TimerTask that is created later.
final Thread t = new Thread(new GuessUntilTimeLimit());
t.start();
long patience = 1000 * 5;
//Use a Timer to enforce your time limit, the TimerTask will execute
// an interrupt of your guessing thread if the thread is still alive
// (it may have died already if user got right answer)
Timer timer = new Timer();
TimerTask task = new TimerTask(){
#Override
public void run() {
if(t.isAlive()){
t.interrupt();
System.out.println("Times up! Enter your final guess now.");
}
}
};
timer.schedule(task, patience);
//Wait for the guessing thread to finish before canceling the timer
t.join();
//By now either the user got the answer or time has run out. Either way
// we need to clean up by canceling the timer.
timer.cancel();
//Added a call to close the scanner, it's always important to release
// resources
scanner.close();
}
Now your main thread schedules a task to execute after patience milliseconds. This task is then responsible for interrupting the "guessing thread". The "guessing thread" will check for interrupt and stop itself when appropriate.
Again, depending on your requirements, you may need to alter the way you accept user input since nextInt will block the thread. For completeness I'm including a link to the question regarding interrupting Scanner.nextLine mentioned in the comments.
Related
I'm trying to write a program that asks simple questions with a time limit on them.
So far I have the following:
public static void main(String[]args) throws IOException, InterruptedException{
Thread thread = new Thread();
Scanner scan = new Scanner(System.in);
System.out.println("1. What is 1+1?");
System.out.println("a. 2\tb. Cannot Be.\tc. 3\td. All of the above.");
String question1 = scan.next();
for(int i = 3; i>=0; i--){
System.out.print("\b"+i);
Thread.sleep(1000);
}
}
This properly asks the question and takes the answer, but it doesn't put a time limit on input and counts down from 3 to 0 after the input is given. What am I doing wrong?
This can be done using a little bit of black multithreading magic.
First, you'll need two threads like this:
Thread thread1 = Thread.currentThread();
Thread thread2 = new Thread(() -> {
try {
for (int seconds = 3; seconds > 0; seconds--) {
System.out.println(seconds+" second"+(seconds == 1 ? "s" : "")+" left");
Thread.sleep(1000);
}
System.out.println("Time's up!");
thread1.stop();
}catch(InterruptedException weCanIgnoreThisException){}
});
where thread1 is the thread that asks the question and thread2 is the countdown.
Then what is left is to ask the question. Don't forget to start() thread2 before asking for input and to stop() it after receiving the input!
System.out.println("1. What is 1+1?");
System.out.println("a. 2\tb. Cannot Be.\tc. 3\td. All of the above.");
thread2.start();
String answer = scan.next();
thread2.stop();
Alright, so here's why I used the deprecated method Thread#stop().
The official documentation of java.lang.Thread explains why is stop() deprecated and what circumstances make it screw up programs:
Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior.
In short, if a thread is stop()ped while it's locked on an object using a synchronized block or method, the lock on the object is released in a dangerously abrupt manner. Since asking multiple choice questions and placing a time limit on input doesn't require a thread to be synchronized on something, we can ignore this.
I would create separate functions to call during the loop, so you don't have a long winded declaration of global variables and such. If you need to control what is called randomly, then you can put a rand in a function and use one global that way, or you can simply put them in a order you want it to be called and completed as.
As you rightly guessed, you need two separate threads running like in the below explanation & code.
The below explanation will provide you more details on what and how you need to do with the two threads.
(1) Thread 1: Timer thread (Inner class implements Runnable) runs in a separate thread and counts the seconds while waiting for the user's input. Once user enters the input this thread needs to be stopped using a signal (stopTimer variable acts as a signal), ensure that stopTimer variable is volatile (to receive the data written by Thread2), otherwise this thread will wait infinitely.
(2) Thread 2: This is the main thread which waits for the user's input. Once the user inputs the data, this main thread signals to stop the Timer thread using a separate method call - signalStopTimer()
public class TimerTest {
public static class Timer implements Runnable {
private volatile boolean stopTimer = false;
private long timerMilliSeconds =0;
#Override
public void run() {
try {
while(!stopTimer) {
Thread.sleep(1000);
timerMilliSeconds = timerMilliSeconds+1000;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void signalStopTimer() {
stopTimer = true;
}
//this method will be helpful to find the elapsed time in seconds
public long getTotalTimeInSeconds() {
return timerMilliSeconds/1000;
}
}
public static void main(String[] args) {
TimerTest.Timer timer = new TimerTest.Timer();
//Start the Timer Thread now
Thread thread = new Thread(timer);
thread.start();
Scanner scan = new Scanner(System.in);
System.out.println("1. What is 1+1?");
System.out.println("a. 2\tb. Cannot Be.\tc. 3\td. All of the above.");
String input = scan.next();
//received the input, signal to stop timer
timer.signalStopTimer();
System.out.println(" input is:"+input+" seconds");
System.out.println(" total time :"+timer.getTotalTimeInSeconds());
}
}
In case you only need to count the time it took until user put his input, the better way and the easiest way is to use System.currentTimeMillis().
before the scan code you can save the current time in a variable (Long), then in while loop (when the loop condition will be stopped when the user put his input) in the end of the loop just save the same way mentioned above the current time in millisecond and then all left is subtraction.
if this is your direction let me know i can supply a code for that ;)
I'm trying to limit attempts of a process in a loop to 60 seconds by sleeping for 3,000ms per loop with 20 attempts. Calling Thread.sleep() isn't actually pausing execution in the thread that's running and instead, all 20 attempts happen rapidly in succession.
private void pollWebServiceForToken() {
final int pollInterval = 3000;
new Thread() {
#Override
public void run() {
int attempts = 0;
int maxAttempts = 60;
String token;
do {
token = requestToken(exchangeCode);
if (token.contains(FAILED)) {
try {
Thread.sleep(pollingInterval);
} catch (InterruptedException ex) {
this.currentThread().interrupt();
}
}
attempts++;
} while (token.toLowerCase().contains(FAILED) && attempts < maxAttempts && !cancelled);
}
}.start();
}
Since this is all happening inside of a Vaadin application, I'm assuming the wrong Thread is being put to sleep but I'm not sure how to target a specific thread for sleeping.
Thanks in advance
Are you sure the code inside the if is being run? The condition on the while is different (+toLowerCase). Thread.sleep() always causes the current thread to sleep.
If I have a loop like this:
for(int i = 0; i <= 10; i++) {
System.out.println("Hello, User " + i;
Thread.sleep(1000)
}
How would I go about adding code that did not require user input, but if the user chose the pause the loop at a given point, they could do so, and resume a few moments later?
For this , you'll need to implement multi-threading. One thread will run the loop(T1) while other can wait for the user input(T2).
T1 - while --> check if input through common bool attribute -->
continue/break loop
T2 - wait for input --> if input=="pause" --> set common attribute to true to
pause loop
Something like :
class MultiThread implements Runnable {
boolean gotInput = false;
int i = 0;
public void run() {
for(;i <= 10 && !gotInput; i++) {
System.out.println("Hello, User " + i;
Thread.sleep(1000)
}
}
public static void main(String args[]) {
MultiThread mt = new MultiThread ();
Thread t = new Thread(mt);
t.start();
Scanner s = new Scanner(System.in);
while (!s.next().equals("pause"));
test.gotInput = true;
}
}
On the same lines you can resume the code if needed.
Try creating a background thread that waits 1 second for the user to select pause. If it is not selected within that 1 second, move forward.
The way this is written, your Thread.sleep() will lock up the UI for 1 second, and regardless of what the user does it won't affect your program.
I'm trying to develop a timer for chess game.
There should be a function like
wait for user input there move from Console
if wait time > 60
stop waiting and keep going.
What I can think of to solve this is using Thread like:
public class Game {
Thread t1 = new PlayDisc(this);
Thread t2 = new Timer(this);
public static void main(String[] args) {
t1.start();
t2.start();
}
}
public class Timer extends Thread{
Game g;
public Timer(Game g) {
this.g = g;
}
#Override
public void run() {
int i = 0;
while(true){
if(i > 6000) {
g.t1.interrupt();
break;
}
}
}
}
public class PlayDisc extends Thread{
private Game g;
public PlayDisc(Game g) {
this.g = g;
}
#Override
public void run() {
Scanner s = new Scanner(System.in);
int x = s.nextInt();
int y = s.nextInt();
Point p = new Point(x, y);
cm.nextPoint = p;
s.close();
}
}
I know this will not work as Scanner.nextInt() is a blocking method. But I'm required to read input from cmd line.
Is there any way to solve this?
There is already a Timer class (in fact two of them, java.util.Timer and javax.swing.Timer). But as you've realized, the blocking nature of nextInt() prevents you from doing anything after the timeout. You would need an additional library that would give you better console control than Java does by default. That, or use Swing.
Edit: It might be possible to perform a hack of some sorts, by using a polling loop with hasNextInt(). That way you wouldn't let the scanning thread block.
Re-Edit: Nah, it's not possible, since hasNext() will block. You'll have to test whether the interrupt will get you out of the trouble here (it might not).
The problem with Scanner is that you don’t have control over the method’s reading more bytes which can always cause blocking. The safe way is to read from System.in manually and create a Scanner which can only read the bytes you already got from the console. Then you can do polling (with sleeping) for implementing a time-out. By choosing the right amount of time for sleeping you get the right balance between responsiveness and CPU usage.
The example program below uses a check interval of 200ms which is good enough to be perceived as “immediate response” by a human user. This value is independent from the wait time which you can configure freely (as long as it is significantly higher than the check interval).
Other things to be aware of is that we calculate a deadline at the beginning rather than aggregating waiting times to be independent of CPU usage within the loop. And we use System.nanoTime() to be independent from changes that might happen to the system’s clock.
long timeOutNS=TimeUnit.MINUTES.toNanos(1); // 1 min timeout
long checkNS=TimeUnit.MILLISECONDS.toNanos(200); // check input every 200ms
int input=0;
boolean hasInput=false;
readWithTimeOut: {
System.out.println("Enter int: ");
long deadLine=System.nanoTime() + timeOutNS;
for(;;) {
int a = System.in.available();
if(a>0) {
byte[] b=new byte[a];
a=System.in.read(b);
if(a<=0) break readWithTimeOut;
Scanner scanner=new Scanner(new ByteArrayInputStream(b, 0, a));
if(scanner.hasNextInt()) {
input=scanner.nextInt();
hasInput=true;
break;
}
else if(scanner.hasNext())
System.err.println("not an int: "+scanner.next()); // consumes token
continue;
}
long remaining=deadLine-System.nanoTime();
if(remaining<=0) {
System.err.println("timeout");
break readWithTimeOut;
}
LockSupport.parkNanos(Math.min(remaining, checkNS));
}
}
System.out.println( hasInput? "entered "+input: "no valid input" );
InputStream.available() is a non-blocking method that you can use to check if there's something in the stream.
If you don't care about spinning (and thus wasting a processor core) that's as simple as it can get:
import java.io.IOException;
import java.util.Scanner;
public class ConsoleReadWithTimeout {
static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) throws Exception {
int i = readIntWithTimeout(5 * 1000);
scanner.close();
}
// returns -1 in case of timeout
static private int readIntWithTimeout(long timeoutInMs) throws IOException {
long startTime = System.currentTimeMillis();
while (System.in.available() == 0) {
if (timeoutInMs < System.currentTimeMillis() - startTime) {
return -1; // or maybe throw a TimeoutException ?
}
}
return scanner.nextInt();
}
}
public class SieveGenerator{
static int N = 50;
public static void main(String args[]){
int cores = Runtime.getRuntime().availableProcessors();
int f[] = new int[N];
//fill array with 0,1,2...f.length
for(int j=0;j<f.length;j++){
f[j]=j;
}
f[0]=0;f[1]=0;//eliminate these cases
int p=2;
removeNonPrime []t = new removeNonPrime[cores];
for(int i = 0; i < cores; i++){
t[i] = new removeNonPrime(f,p);
}
while(p <= (int)(Math.sqrt(N))){
t[p%cores].start();//problem here because you cannot start a thread which has already started(IllegalThreadStateException)
try{
t[p%cores].join();
}catch(Exception e){}
//get the next prime
p++;
while(p<=(int)(Math.sqrt(N))&&f[p]==0)p++;
}
//count primes
int total = 0;
System.out.println();
for(int j=0; j<f.length;j++){
if(f[j]!=0){
total++;
}
}
System.out.printf("Number of primes up to %d = %d",f.length,total);
}
}
class removeNonPrime extends Thread{
int k;
int arr[];
public removeNonPrime(int arr[], int k){
this.arr = arr;
this.k = k;
}
public void run(){
int j = k*k;
while(j<arr.length){
if(arr[j]%k == 0)arr[j]=0;
j=j+arr[k];
}
}
}
Hi I'm getting an IllegalThreadStateException when I run my code and I've figured it's because I am trying to start a thread that has already been started. So how could I kill
or stop the thread each time, to get around this problem?
how could I kill or stop the thread each time, to get around this problem?
The answer is, you can't. Once started, a Thread may not be restarted. This is clearly documented in the javadoc for Thread. Instead, what you really want to do is new an instance of RemoveNonPrime each time you come around in your loop.
You have a few other problems in your code.
First, you need to increment p before using it again:
for(int i = 0; i < cores; i++){
t[i] = new removeNonPrime(f,p); //<--- BUG, always using p=2 means only multiples of 2 are cleared
}
Second, you might be multithreaded, but you aren't concurrent. The code you have basically only allows one thread to run at a time:
while(p <= (int)(Math.sqrt(N))){
t[p%cores].start();//
try{
t[p%cores].join(); //<--- BUG, only the thread which was just started can be running now
}catch(Exception e){}
//get the next prime
p++;
while(p<=(int)(Math.sqrt(N))&&f[p]==0)p++;
}
Just my $0.02, but what you are trying to do might work, but the logic for selecting the next smallest prime will not always pick a prime, for example if one of the other threads hasn't processed that part of the array yet.
Here is an approach using an ExecutorService, there are some blanks (...) that you will have to fill in:
/* A queue to trick the executor into blocking until a Thread is available when offer is called */
public class SpecialSyncQueue<E> extends SynchronousQueue<E> {
#Override
public boolean offer(E e) {
try {
put(e);
return true;
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
return false;
}
}
}
ExecutorService executor = new ThreadPoolExecutor(cores, cores, new SpecialSyncQueue(), ...);
void pruneNonPrimes() {
//...
while(p <= (int)(Math.sqrt(N))) {
executor.execute(new RemoveNonPrime(f, p));
//get the next prime
p++;
while(p<=(int)(Math.sqrt(N))&&f[p]==0)p++;
}
//count primes
int total = 0;
System.out.println();
for(int j=0; j<f.length;j++){
if(f[j]!=0){
total++;
}
}
System.out.printf("Number of primes up to %d = %d",f.length,total);
}
class RemoveNonPrime extends Runnable {
int k;
int arr[];
public RemoveNonPrime(int arr[], int k){
this.arr = arr;
this.k = k;
}
public void run(){
int j = k*k;
while(j<arr.length){
if(arr[j]%k == 0)arr[j]=0;
j+=k;
}
}
}
You could implement Runnable instead and use new Thread( $Runnable here ).start() or use a ExecutorService to reuse threads.
* It is never legal to start a thread more than once.
* In particular, a thread may not be restarted once it has completed
* execution.
*
* #exception IllegalThreadStateException if the thread was already started
*/
public synchronized void start() {
In Android, document still mention that we will get IllegalThreadStateException if the thread was already started.
However for some device it will not throw this exception (tested on Kyocera 7.0). In some popular device like Samsung, HTC, it throw throw the exception normally
I answer here because the Android question is mark as duplicated to this question.
Why does an IllegalThreadStateException occur when Thread.start is
called again
Because JDK/JVM implementers coded Thread.start() method that way. Its a reasonable functional expectation to be able to restart a thread after a thread has completed its execution and that is what being suggested in chrisbunney's answer ( and I have put in a comment in that answer ) but if you look at Thread.start() implementation , the very first line is ,
if (threadStatus != 0)
throw new IllegalThreadStateException();
where threadStatus == 0 means NEW state so my guess is that implementation doesn't resets this state to zero after execution has completed & thread is left in TERMINATED state ( non - zero state ). So when you create a new Thread instance on same Runnable , you basically reset this state to zero.
Also, I noticed the usage of word - may & never in same paragraph as different behavior is being pointed out by Phan Van Linh on some OSes,
It is never legal to start a thread more than once. In particular, a
thread may not be restarted once it has completed execution.
I guess what they are trying to say in above Javadoc that even if you don't get IllegalThreadStateException on certain OS, its not legal in Java/Thread class way & you might get unexpected behavior.
The famous thread state diagrams depict the same scenario - no going back from dead state to new.
ThreadPools can be used for delivering tasks to set number of threads. When initiating you set the number of threads. Then you add tasks for the pool. And after you can block until all tasks have finished processing. Here is some sample code.
I am not at all sure I understand the question. All the methods for stopping threads that are executed from other threads are deprecated; the way to stop a thread is to have it check a variable that it and another thread can access (perhaps a volatile variable), and have the running thread check it occasionally to see if it should exit on its own.
I cannot tell why/whether you want to eliminate the running thread and use another one, and I cannot see how the different threads are going to help execute your overall goal any faster. But it's possible I'm just not understanding the math.
The Thread.isAlive() method can tell you if the Thread has already been started. Simply do this where you want to start your thread:
if(!t[p%cores].isAlive()){
t[p%cores].start();
}