I got this as an interview question.
why isn't Thread class final? Why would you extend a Thread ever?
I could not come up with real world use cases.
I got this as an interview question.
why isn't Thread class final? Why would you extend a Thread ever?
I could not come up with real world use cases.
From Oracle's documentation:
There are two ways to create a new thread of execution. One is to declare a class to be a subclass of Thread. This subclass should override the run method of class Thread. The other way to create a thread is to declare a class that implements the Runnable interface.
So the answer is "you may want to subclass Thread
to override its run()
method."
The quoted paragraphs have been in the Java documentation going back as far as JDK 1.1. Java has added other convenient classes for managing concurrency, most notably, the executors mentioned in the comments, possibly diminishing or eliminating the need to extend Thread
. They cannot make it final
, however, because that would break backward compatibility.
As far as practical reasons go, I think the only reason you may want to extend Thread
rather than implement Runnable
today would be to override its methods other than run()
. For example, you may want to add logging or additional clean-up.
This is pretty much just taken from John Vint's comment, but I think it's the best answer.
The only time I can think of where I might extend Thread
rather than implementing Runnable
-- or, even better, just using an ExecutorService
with a Future
-- is when I needed to override Thread.interrupt()
to do some cleanup. Otherwise, I can't see any practical reason to actually extend Thread
.
Two cases:
Thread
, perhaps one that cleans up some resource after finishing, etcrun()
method, rather than providing a Runnable
to the constructor (note: avoid this pattern - it's not the right approach)Another reason that Thread
is not final is that in the early days of Java, overriding run()
was considered to be a good design pattern. (I guess, in the days before anonymous classes, it was thought to be "neater" to subclass Thread
than to create a free-standing class that implements Runnable
.)
Anyway, once Java 1.0 was released it because impossible to fix the problem by changing Thread
to be final. That would have broken a lot of existing code.
Let me put this in the following way: When designing a language, which is a tool like any other, one should think in terms of pros and cons and not just limit the tool because we aren't able to see applicable real use cases. By doing this we are able to understand such decisions theoretically. Basically, the exercise is asking the other way round.
Why Thread should be final?
Let me get to the point.
(I'm not including the backward compatibility argument, personally, I don't like it, as I think we should always be focused on improving locally)
To be able to discuss such subject we need to understand the benefits of declaring a class as final or not.
Here TofuBeer said:
Virtual (overridden) methods generally are implemented via some sort of table (vtable) that is ultimately a function pointer. Each method call has the overhead of having to go through that pointer. When classes are marked final then all of the methods cannot be overridden and the use of a table is not needed anymore - this it is faster.
Some VMs (like HotSpot) may do things more intelligently and know when methods are/are not overridden and generate faster code as appropriate.
Here oracle highlights:
It is better to design APIs with security in mind. Trying to retrofit security into an existing API is more difficult and error prone. For example, making a class final prevents a malicious subclass from adding finalizers, cloning, and overriding random methods.
There is also issues with invariants and sensitive information. However, all security concerns are project specific and not applicable to a tool which can be used in non-security-concerned scenarios.
andersoj referred here this nice IBM article:
final classes and methods can be a significant inconvenience when programming -- they limit your options for reusing existing code and extending the functionality of existing classes. While sometimes a class is made final for a good reason, such as to enforce immutability, the benefits of using final should outweigh the inconvenience. Performance enhancement is almost always a bad reason to compromise good object-oriented design principles, and when the performance enhancement is small or nonexistent, this is a bad trade-off indeed.
So, from my point of view, if there is no strong benefit to set the class as final, if JVM's are capable of doing such performance optimisations, I would say the convenient argument wins.
As so, we can extend the Thread class and do whatever we want with it, some initialization/finalization stuff, like logging, change the thread names, the type of thread... It up to you!
It may be fields to hold the thread-local variables in the derived Thread
class. Such variables can be accessible also when run()
methods is not overridden and the thread executes Runnable
s as usual. Such custom threads may be managed by the standard ExecutorService
, creating them in the custom ThreadFactory
and discarding as required.
I am aware there is also ThreadLocal
, but if the fields require cleanup (say they are the database connections), this can be rather elegantly done by calling super.run()
to process Runnable
s and putting finalization immediately before the run
method returns (so the thread terminates).