Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread object constructed by runnable overrides the run method

Tags:

java

scjp

Given this sample code:

Runnable r = new Runnable() {
  public void run() {
    System.out.print("Cat");
  }
};
Thread t = new Thread(r) {
  public void run() {
    System.out.print("Dog");
  }
};
t.start();

why is the output Dog and not Cat??

like image 727
Eslam Mohamed Mohamed Avatar asked Sep 05 '12 16:09

Eslam Mohamed Mohamed


2 Answers

The implementation of run in Thread simply calls the Runnable provided in the constructor, if there is one. You're overriding that code, so if the new thread simply has its run method called regardless, the Runnable is ignored. Of course, you should be able to look at the source code to check that... (I've just done so, and while I'm not going to post the source here, it does exactly what I've described.)

What you've really exposed is an encapsulation problem - Thread shouldn't have these different, potentially conflicting, ways of saying what the thread should do. Basically, you should almost never extend Thread directly. Just because it's been designed badly doesn't mean you have to abuse that poor design ;)

EDIT: This is actually documented, in a somewhat roundabout way. start() is documented as:

Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.

And run() is documented as:

If this thread was constructed using a separate Runnable run object, then that Runnable object's run method is called; otherwise, this method does nothing and returns.

So the run() method is called as per start(), but you've overridden run(), which is the only method which will call the Runnable provided in the constructor.

Note that if you'd overridden the method like this:

Thread t = new Thread(r) {
  public void run() {
    super.run();
    System.out.print("Dog");
  }
};

Then the output would be "CatDog".

like image 59
Jon Skeet Avatar answered Sep 30 '22 04:09

Jon Skeet


You have overridden Thread.run so that it doesn't execute the runnable. Instead it just prints "Dog".

like image 30
Erick Robertson Avatar answered Sep 30 '22 02:09

Erick Robertson