Reputation: 127
I searched StackOverflow but I couldnt find the answer to my question.
I have a class Main:-
public class Main {
public static Thread game = new Thread(new Start());
public static void main(String[] args) {
game.start();
try {
game.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
And I have the game Thread(start class):-
public class Start implements Runnable {
private Timer timer = new Timer();
private Thread timerThread = new Thread(timer, "timer");
@Override
public void run() {
...
try {
play();
}
catch(IOException e) {
e.printStackTrace();
}
}
public void play() throws IOException {
...
timerThread.run();
System.out.print("Enter a letter: ");
char input = sc.next().toUpperCase().charAt(0);
...
if(isPlaying) play();
}
}
And I have the Timer class:-
public class Timer implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 15; i++) {
try {
System.out.println(i);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.game.interrupt();
}
}
Now the problem comes that when I start the game, the timer also starts. But at the end of 15 seconds, Timer thread stops. But the program didn't stop executing.
After 15 seconds, the compiler is still willing to take the input. After the input, the program ceases.
I want to immediately force stop the thread. Soon after 15 seconds, I want to stop the execution of the game thread at that very instant.
I looked over at some Multithreading tutorials on Youtube and some previously asked questions at StackOverflow but I failed to find a solution.
Upvotes: 0
Views: 72
Reputation: 694
Are you receiving a NullPointerException
?
I tested your solution and that's what I got.
If that's the case, your problem is that you are trying to initialize the game
field in Timer
before the static property in the Main
class is initialized.
For the sake of your understanding let me rephrase that: When your code runs
private Thread game = Main.game;
there is nothing in Main.game
and that's because Main.game
will be initialized after the initialization of the Start
and Timer
instances.
The simplest way to solve it is to remove the private Thread game
property of your Timer and just call Main.game.interrupt();
Edit 01:
Once you solve the first thing, you need to understand how the thread interruption works.
When you call Main.game.interrupt();
, you are only going to stop it immediately if the thread is sleeping. If that's the case, the thread will throw an InterruptedException
but that's not what we want and I wouldn't recommend it. In a normal flow, the execution of the .interrupt()
method will set the status of the destination thread as "Interrupted" but that is only a boolean
flag that doesn't change anything (yet). What you need to do, is to check the status of that flag in your recursion method so when the value the "interruption" flag is equal to true, you will change the value of isPlaying
to false. And that's how your thread will stop.
In code it would be something like this:
public void play() throws IOException {
...
timerThread.run();
System.out.print("Enter a letter: ");
char input = sc.next().toUpperCase().charAt(0);
if (Thread.interrupted()) {
System.out.println("I should interrupt myself! ;)");
isPlaying = false;
}
...
if(isPlaying) play();
}
Hope this helps :)
Upvotes: 2