Please correct me if I am wrong but I executed your code after I inserted
some flag messages and I have noticed the execution passes the notify in both casess so there is no difference if we extend Thread or if we implement Runnable.
please take a look at the code (Eclipse 3.1 and Window 2000 J2SDK 1.4.2_07)
A- extends Thread
<result>
Waiter is holding the lock now inside the synchronized block
Waiter will wait
Notifier will sleep
Notifier waked up from a sleep
Notifier holding the lock before notify call
Notifier holding the lock after notify call
Waiter is back to run
Waiter IS NOT holding the lock now outside the synchronized block
Waiter is awakened
Waiter is holding the lock now inside the synchronized block
Waiter will wait
NotifierIS NOT holding the lock outside the synchronized block
Notifier will sleep
Notifier waked up from a sleep
Notifier holding the lock before notify call
Notifier holding the lock after notify call
Waiter is back to run
Waiter IS NOT holding the lock now outside the synchronized block
Waiter is awakened
Waiter is holding the lock now inside the synchronized block
...etc
</result>
<code>
class Waiter extends Thread {
Waiter(
String name){
super(name);
}
public void run(){
while(true){
synchronized(this){
if (Thread.currentThread().holdsLock(this))
System.out.println(Thread.currentThread().getName() + " is holding the lock now inside the synchronized block");
try {
System.out.println(Thread.currentThread().getName() + " will wait");
wait();
System.out.println(Thread.currentThread().getName() + " is back to run");
}catch(InterruptedException ie){
throw new RuntimeException();
}
}
if (Thread.currentThread().holdsLock(this))
System.out.println(Thread.currentThread().getName() + " is holding the lock now outside the synchronized block");
else
System.out.println(Thread.currentThread().getName() + " IS NOT holding the lock now outside the synchronized block");
System.out.println(" Waiter is awakened");
}
}
}
class Notifier extends Thread {
private Thread ot;
Notifier(Thread otherThread, String name){
super(name);
ot = otherThread;
}
public void run(){
while(true){
try {
System.out.println(Thread.currentThread().getName() + " will sleep");
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " waked up from a sleep");
} catch(InterruptedException ie) {
throw new RuntimeException();
}
synchronized(ot){
if (Thread.currentThread().holdsLock(ot))
System.out.println(Thread.currentThread().getName() + " holding the lock before notify call");
ot.notify();
if (Thread.currentThread().holdsLock(ot))
System.out.println(Thread.currentThread().getName() + " holding the lock after notify call");
else
System.out.println(Thread.currentThread().getName() + " IS NOT holding the lock after notify call");
}
if (Thread.currentThread().holdsLock(ot))
System.out.println(Thread.currentThread().getName() + " holding the lock outside the synchronized block");
else
System.out.println(Thread.currentThread().getName() + "IS NOT holding the lock outside the synchronized block");
}
}
}
public class Threads {
public static void main(String[] args) {
Thread t1 = new Waiter("Waiter");
Thread t2 = new Notifier(t1, "Notifier");
t1.start();
t2.start();
}
}
</code>
B- Runnable
<result>
Waiter is holding the lock now inside the synchronized block
Waiter will wait
Notifier will sleep
Notifier waked up from a sleep
Notifier holding the lock before notify call
Notifier holding the lock after notify call
Waiter is back to run
Waiter IS NOT holding the lock now outside the synchronized block
Waiter is awakened
Waiter is holding the lock now inside the synchronized block
Waiter will wait
NotifierIS NOT holding outside the synchronized block
Notifier will sleep
Notifier waked up from a sleep
Notifier holding the lock before notify call
Notifier holding the lock after notify call
Waiter is back to run
Waiter IS NOT holding the lock now outside the synchronized block
Waiter is awakened
Waiter is holding the lock now inside the synchronized block
Waiter will wait
NotifierIS NOT holding outside the synchronized block
Notifier will sleep
... etc
</result>
<code>
class Waiter implements Runnable {
public void run(){
while(true){
synchronized(this){
if (Thread.currentThread().holdsLock(this))
System.out.println(Thread.currentThread().getName() + " is holding the lock now inside the synchronized block");
try {
System.out.println(Thread.currentThread().getName() + " will wait");
wait();
System.out.println(Thread.currentThread().getName() + " is back to run");
}catch(InterruptedException ie){
throw new RuntimeException();
}
}
if (Thread.currentThread().holdsLock(this))
System.out.println(Thread.currentThread().getName() + " is holding the lock now outside the synchronized block");
else
System.out.println(Thread.currentThread().getName() + " IS NOT holding the lock now outside the synchronized block");
System.out.println(" Waiter is awakened");
}
}
}
class Notifier implements Runnable {
private Runnable waiter;
Notifier(Runnable waiter){
this.waiter = waiter;
}
public void run(){
while(true){
try {
System.out.println(Thread.currentThread().getName() + " will sleep");
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " waked up from a sleep");
} catch(InterruptedException ie) {
throw new RuntimeException();
}
synchronized(waiter){
if (Thread.currentThread().holdsLock(waiter))
System.out.println(Thread.currentThread().getName() + " holding the lock before notify call");
waiter.notify();
if (Thread.currentThread().holdsLock(waiter))
System.out.println(Thread.currentThread().getName() + " holding the lock after notify call");
else
System.out.println(Thread.currentThread().getName() + " IS NOT holding the lock after notify call");
}
if (Thread.currentThread().holdsLock(waiter))
System.out.println(Thread.currentThread().getName() + "holding outside the synchronized block");
else
System.out.println(Thread.currentThread().getName() + "IS NOT holding outside the synchronized block");
}
}
}
public class Runnables {
public static void main(String[] args) {
Waiter waiter = new Waiter();
Thread t1 = new Thread(waiter, "Waiter");
Thread t2 = new Thread(new Notifier(waiter), "Notifier");
t1.start();
t2.start();
}
}
</code>
thank you