• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Liutauras Vilda
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Saloon Keepers:
  • Scott Selikoff
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
  • Frits Walraven
Bartenders:
  • Stephan van Hulst
  • Carey Brown

Beginner: Threads vs. Runnables

 
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm doing my first concurrency exercices. I can't figure out why the following works when my objects subclass Thread but don't when they implement Runnable:

Works:



Doesn't work (seems that notify() never "gets through"):

 
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In your example, when you inherit from the Thread class, both threads use the *same* object for notifications -- the thread object of the waiter.

In your example, when you use runnables, the two threads are *not* using the same object. The notify thread is using the wait thread object, while the wait thread is using the runnable object embedded in the wait thread object.

Henry
 
Randy Gibbons
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I see the light, thanks. In my greenhornness, I wasn't distinguishing between the thread object itself and the potentially different Runnable object containing the thread's task.
A mild criticism of Eckel's chapter on Concurrency (Thinking in Java, 3rd Edition), which is my introduction to the topic: Since he has an expressed preference for subclassing Thread rather than using Runnable (since, where appropriate, the Thread subclass can be an inner class and therefore not prevent the outer class from inheriting from something else), he doesn't have many examples using Runnable. Seems to me my confusion would be common among beginners and should be addressed in an introductory text (nevertheless, I find the Eckel book awesome).
I'm off to Borders this afternoon to buy your 3rd edition on Threads.
For those following this "thread," here is a version of "Runnables" that works:
 
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Politics n. Poly "many" + ticks "blood sucking insects". Tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic