I know the differences between the concrete Thread class and the Runnable Interface in Java. ... Can all threads be created by implementing the Runnable interface? What will be the use case where the Thread class is a necessity?
You cannot create a thread just by implementing the Runnable interface. There must always be a Thread
even when there is also a separate Runnable
. The Thread
class is essential for multi-threading in Java programs.*
But note! That doesn't mean your own code must execute new Thread(...)
or new MyFoobarThread()
.
Why we have two ways to solve the same problem ?
We have many ways to solve the problem: Your code could ask a ThreadFactory
to create new instances. Your code could create a ThreadPoolExecutor
instance, and let the executor manage the threads. Your code could use parallel streams, which are based on threads. Your code could call a third party library that uses threads. But, no matter how it happens, there will always be one Thread
instance for each thread in the program.
[* A native
method could create a thread for which there was no corresponding Thread
instance, but in that case, the thread would be incapable of calling Java methods, and Java code would be completely unaware that the thread existed.]
What is the need for making the Thread class overridable...?
It's not a question of need. Thread
is a class. Every class that is not final
can be extended. What would be the purpose of making Thread
final? What would be the reason to prevent programmers from extending it if extending it solved some problem? (I know of problems that could be solved by extending Thread
and wrapping certain of its methods, but I won't go in to that here.)
The purpose of programming languages is to help programmers to do what they need to do, not to put roadblocks in their way.
Runnable
originally was created for use with the Thread
class—Stephen C told you a bit about the history of that, and Shubh told you a bit about the reason for it—But Runnable
, it turns out, is useful for much more than just threading.
Runnable
is a behavioral contract. It describes a "thing that needs to happen," a "piece of work that needs to be done." It does not describe who does the work or, when they do it. The work could be done by a Thread
now, it could be done by a thread pool as soon as possible, it could be done by a timer at some appointed time, it could be done by a third party library after some other task has been completed, etc.
A Thread
has a Runnable
just like how a coffee pot has a handle. Having a handle greatly improves the usefulness of a coffee pot, but other things have handles too, for reasons that have nothing to do with making coffee.