When i try to kill my Robber threads, some die , but some get stuck in the wait() block , what would be a better way to kill all the threads , or how do i get the blocked threads out to be killed?
private int robberId;
private static int robberGlobalId=0;
private TreasureChest chest;
private boolean alive = true;
public Robber(TreasureChest chest) {
robberId = robberGlobalId;
robberGlobalId++;
this.chest = chest;
}
public void run() {
while (alive) {
try {
synchronized(chest){
robCoin();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Robber " +robberId +" just died");
}
public void robCoin() throws InterruptedException {
if (chest.getTreasureAmount() <= 0 ) {
chest.wait();
} else {
chest.removeCoin();
}
Thread.sleep(50);
}
public void killRobber() {
alive = false;
}
When i try to kill my Robber threads, some die , but some get stuck in the wait() block , what would be a better way to kill all the threads ,
The right way to "kill" a thread is to interrupt it with thread.interrupt()
. If the thread is blocked in a wait(...)
call, this will immediately throw InterruptedException
. When you catch InterruptedException
it is a good idea to immediately re-interrupt the thread to preserve the interrupt flag because when the exception is thrown, the interrupt bit is cleared.
try {
...wait();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
// handle the interrupt
return;
}
Since not all methods throw InterruptedException
, you can also check to make sure the thread has been interrupted with something like the following:
if (Thread.currentThread().isInterrupted()) {
// stop processing
return;
}
Or in your case something like:
while (alive && !Thread.currentThread().isInterrupted()) {
Btw, alive
should be volatile
because it looks to be accessed by multiple threads.
Interrupting the thread is one way to do it as demonstrated in @Gray's answer, however it might be cleaner to wake up waiting threads when you "kill" the Robber instead of interrupting them.
In this example below the "Robber task" (implemented by the run()
method) will wait as long as the robber is alive and the chest is empty ( less than or equal to 0). If killRobber()
is called waiting threads are woken up and exit run()
gracefully (alive will be false
).
public void run() {
try{
synchronized(chest){
while (chest.getTreasureAmount() <= 0 && alive) {
chest.wait();
}
if(alive){
chest.removeCoin();
}
}
}catch (InterruptedException ie){
/* Thread interrupted do something appropriate,
which may be to do nothing */
}
}
public void killRobber() {
synchronized(chest){
alive = false;
chest.notifyAll();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With