Why does Thread implement Runnable?
A Java Thread's run() method is called by the JVM, on that thread, when the thread starts. To give a thread something to do, you can make a subclass of Thread and override its run() method, or (preferred) you can supply a Runnable to the thread's constructor. That's fine.
I was in the midst of making a subclass of Thread and overriding run, and I realized I couldn't make the method protected as I expected to because Thread.run() is public. Then I realized why: it has to be public because Thread implements Runnable. But why does it implement Runnable?
It doesn't seem logical. A thread is startable (from the current thread), but you don't run it in the same way you run() a Runnable (from the current thread); the thread runs itself (on its own thread). If you do call a Thread's run method manually, then you're not using it as a Thread, just a heavyweight Runnable.
Because of the design, any code with access to a Thread object can call its public run method and potentially poke into code that is not intended to be public or designed to be called that way. It also allows very peculiar things like this:
Thread.currentThread.run();
Is there a legitimate use for Thread implementing Runnable that I'm not seeing?
The reason is "backwards compatibility".
The Thread
class originated in Java 1.0 ... or earlier. In those days, Java didn't have inner classes, and so there wasn't a light-weight way to implement a Runnable
instance. If you look at old threading examples and tutorials from that era, it is common to see classes that extend Thread
and override the run()
method.
Over time, it was realized that extending Thread
is not a good idea (for various reasons). However, the Thread
design could not be changed because that would have made old Java code incompatible with newer JVMs.
Is there a legitimate use for Thread implementing Runnable that I'm not seeing?
It depends what you mean by "legitimate".
Old code that was written in the early days is not "illegitimate" by virtue of doing things the old way. There is nothing "broken" about it.
There are potentially scenarios where it does make sense to extend Thread and override the run()
method. For example, you might want run()
to implement some special mechanism for passing info in or out of the supplied Runnable
, or implement some special exception handling, or ... make the thread "restartable".
There might even be scenarios where you'd want to call run()
directly on a thread object. For instance if you were handed some "dogs breakfast" code that extended Thread
and you had to convert it to run in a thread pool without modifying the original code. You might consider instantiating the crufty thread class and passing the instances as runnables to the threadpool to run. (Yes ... horrible!)
Overriding run doesn't explain why it ever needed to be public though.
If this is your issue, I think there's simple answer for that: methods implementing an interface must always be public in java. It would be possible with an abstract class for it to be protected, but if Thread were abstract, you wouldn't be able to use it as such.
As to why is Thread implementing Runnable in the first place, java must have a way of knowing at which part the thread is actually doing its job. They use run method for that. They could have more clearly separated the logic of just implementing Runnable and having Thread subclass implement that, but that is what I consider a minor mistake which is hard to change due to historical reasons.
TLDR; AFAIK there really isn't a good reason for a Thread to implement Runnable, but there is reasons for it to implement some kind of interface like that - they should've just probably had some kind of separated interface like ThreadRunnable instead of using the same Runnable interface that has other uses as well.
Note also that on modern java you should probably anyway use Callables and FutureTasks instead of Threads. "The integration of timeouts, proper cancelling and the thread pooling of the modern concurrency support are all much more useful to me than piles of raw Threads.", quoting another answer here on stackoverflow.
链接地址: http://www.djcxy.com/p/16390.html上一篇: 实现Runnable而不是扩展Thread时的不同行为
下一篇: 为什么线程实现可运行?