When I run this code, it displays the following output:
One : 15
Two : 15
One : 14
Two : 14
Two : 13
One : 13
Two : 12
One : 12
One : 11
Two : 11
Thread 1 suspended
Two : 10
Two : 9
Two : 8
Two : 7
Two : 6
Thread 1 resumed
Thread 2 suspended
Thread 2 resumed
The output doesn't continue till the end that is One:1 Two:1 Is the myresume method of NewThread1 class not executed? What is the reason behind this?
Following is the code of NewThread1:
class NewThread1 implements Runnable{
String name;
Thread t;
boolean suspendFlag;
NewThread1(String threadname){
name = threadname;
t = new Thread(this, name);
suspendFlag = false;
t.start();
}
@Override
public void run(){
try{
for(int i=15; i>0; i--){
System.out.println(name+ " : " +i);
Thread.sleep(200);
synchronized(this){
while(suspendFlag){
wait();
}
}
}
}catch(InterruptedException e){
System.out.println("New thread1 Interrupted");
}
}
synchronized void myresume(){
suspendFlag = false;
}
void mysuspend(){
suspendFlag = true;
}
}
Following is the code of NewThread1:(main() method is defined here)
public class Suspend_ResumeThreads {
public static void main(String args[]){
NewThread1 ob1 = new NewThread1("One ");
NewThread1 ob2 = new NewThread1("Two ");
try{
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Thread 1 suspended");
Thread.sleep(1000);
ob1.myresume();
System.out.println("Thread 1 resumed");
ob2.mysuspend();
System.out.println("Thread 2 suspended");
Thread.sleep(1000);
ob2.myresume();
System.out.println("Thread 2 resumed");
}catch(InterruptedException e){
System.out.println("Main Interrupted");
}
try{
ob1.t.join();
ob2.t.join();
}catch(InterruptedException e){
System.out.println("Main interrupeted in join()");
}
System.out.println("Main exiting..");
}
}
Use notifyAll
to interrupt a wait()
: put
this.notifyAll();
into your myresume()
function. But always be prepared for this notification to get lost; in particular when no thread is currently waiting then it will still succeed.
Make sure you synchronize
/wait
/notify
on the same object. A common error is to synchronize on this
and not realize that in the context of an anonymous inner class, this
could be something different. And even worse, it can change when refactoring the code! A best practice is to have an Object lock = new Object();
somewhere and always synchronize(lock) ... lock.wait(); ... lock.notifyAll();
to avoid such programming (and refactoring) errors.
Unless you make suspendFlag
volatile
, there is also a chance that different threads see different values of this field (if it is not volatile
, threads may keep a local copy in the CPU cache). Thus, it may also be good to make mysuspend
synchronized, too.
In some cases you may need to switch to a more advanced synchronization, such as java.util.concurrent.locks.Lock and java.util.concurrent.Semaphore.