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??
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??
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".
Thread
or passes a Runnable
as the task that the Thread
must run.This is what the documentation specifies.If this can be misused as per the OP trick question, why is this a bad design? –
Mcmann Thread
has been a final
class and had forced you to pass in a Runnable
. –
Wondawonder Thread
and creating custom threads, setting daemon
as needed and ThreadGroup
etc prior to concurrent
package.This seems to be useful (back then) and this would not be possible though if the Thread
was made as final
. –
Mcmann Thread
rather than just creating an instance and setting properties? Subclassing should be about changing behaviour, not just setting values. –
Wondawonder Thread
just to set some properties, then yes. There's nothing thread-specific there - it's an abuse of inheritance, IMO. –
Wondawonder You have overridden Thread.run
so that it doesn't execute the runnable. Instead it just prints "Dog".
Runnable
has been given, call that - otherwise, call the run
method." (Actually, start()
is documented to call run
, but the whole class could have been designed differently.) –
Wondawonder Thread.run()
, which is not a native
method, how could this vary by implementation? –
Triclinium It is because the function run()
is overridden. And t
call this function:
public void run() {
System.out.print("Dog");
}
You will get the o/p as cat
when you execute r.start()
Which will call the function
public void run() {
System.out.print("Cat");
}
run()
is not overloaded. It's overridden, which is different... and the rest of your answer doesn't really provide much enlightenment. –
Wondawonder Taking a look at the source code for java.lang.Thread
:
public void run() {
if (target != null) {
target.run();
}
}
target
is the Runnable
field in the Thread
that the Thread(Runnable)
constructor uses to assign your r
variable. When you override the run
method in the Thread
, you're changing the behavior of run
to call
System.out.print("Dog");
instead of calling
if (target != null) {
target.run();
}
This is an anonymous class and you are redefining/overriding run
. Are you using the passed-in Runnable
inside your run
? No you don't. So the question is, why did you expect it to print Cat
?
new Thread(r) {
public void run() {
System.out.print("Dog");
}
};
Cat
printed.I answered that.Because he ignores Runnable
passed in. –
Mcmann Thread
doesn't necessarily have to work that way, a better answer would have been reminding him that Thread.run
calls his runnable's run method, and that overriding it removed that behavior. –
Landwaiter Thread(Runnable target)
that ignores the target
when the thread is run
? –
Mcmann 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 this is how it is specified.It is not implementation detail.Taken from docs.oracle.com/javase/7/docs/api/java/lang/… –
Mcmann © 2022 - 2024 — McMap. All rights reserved.
Thread
you can do@Override public void run() { super.run(); System.out.print("Dog"); }
, and you'll get both.) – Wetnurse