1

I know the differences between the concrete Thread class and the Runnable Interface in Java . What is the need for making the Thread class overridable so that it is available for consumption ? Can all threads be created by implementing the Runnable interface ? What will be the use case where the Thread class is a necessity? Why we have two ways to solve the same problem ?

Edit : I understand the Thread class is the container for the Runnable implementations , I want to know whether there are any use cases which is unsolvable by Runnable implementations

Thaveedu
  • 101
  • 1
  • 8
  • `Thread` is non-reentrant, that is, once it's completed running, you can't restart it. So, instead, when needed, you create a `Thread` and pass it the instance of `Runnable` you want executed, so you can "re-run" an instance of `Runnable` multiple times ... if that's a thing you want to do. It also falls into the design principle of "composition over inheritance", I mean, honestly, how many times do you really need to extend `Thread`? What "new" functionality would you possibly add to it? – MadProgrammer Apr 08 '22 at 04:10

4 Answers4

6

Why Java provides both the Thread Class and Runnable Interface for creating Threads?

The short answer is "history".

In ~1995, Java 1.0 defined Thread so that you can either extend the class, or pass a Runnable to the constructor. By about Java 1.1, it was pretty clear to the designers that extending Thread was a poor choice. But it was too late to fix. Changing Thread to be a final class was no longer an option, since it would break backwards compatibility.

Roll forward to 2022 and the same reasoning still applies. There is still lots of important legacy code where programmers have extended Thread to override run() with a method containing application logic. The code works fine ... so forcing lots of Java users to update to a "better" way would be a bad business decision.


Why did they make the decision in the first place? Who knows! My guess is that back in 1995 they didn't envisage things like thread pools, executors and so on that are problematic if you extend Thread. (And a few other things ... as illustrated by the unsafe or unimplementable Thread methods that were deprecated many years ago.)

One possible factor is that Java 1.0 didn't have anonymous inner classes. So, to use the constructor parameter approach, programmers needed to declare a named class that extended Runnable. Extending Thread was an "attractive" alternative. IIRC, that language shortcoming was addressed in Java 1.1. And in Java 8+ we can also use lambda expressions to define thread runnables.

Remember: threads were a new thing when Java was designed. Java was one of the first programming languages to support them properly. (The only way to guarantee not to make mistakes is to not do anything. And that is often a bigger mistake.)


Can all threads be created by implementing the Runnable interface ?

No. All of the logic involved in creating a thread is actually in the Thread class ... and its native code implementation in the JVM. It is not practical to do this yourself in Java code.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • I know the concrete Thread class is underlying container for the Runnable Interface to run , My question is since we can create asynchronous tasks by implementing the Runnable type Are there any use case(s) or some workflow where the Thread class is necessary? – Thaveedu Apr 08 '22 at 05:09
  • I see both Thread and Runnable is available since Java 1.0 so backward compatibility might not be a reason to support both at the same time. https://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html . Is there any document on the design choices made during Java 1.0 or Java1.1 – Thaveedu Apr 08 '22 at 05:36
  • Well ... obviously ... all of them, since threads don't work if you don't use `Thread`. Are you really asking if there are use-cases where it is necessary to extend `Thread`? – Stephen C Apr 08 '22 at 05:38
  • Yes exactly , Is there are use-cases where it is necessary to extend ? – Thaveedu Apr 08 '22 at 05:39
  • That's not what I am saying in my answer. The backward compatibility issue is that you cannot declare `Thread` as `final` or remove the `Thread(Runnable)` constructor, because either of those things would stop old code from running. – Stephen C Apr 08 '22 at 05:40
  • The use cases where you need to extend `Thread` is when you are implementing your own version of `Executor` from scratch, or your own thread pool class. In some use-cases you need to change the way that the standard `Thread` class does certain things; e.g. to intercept exceptions from the applications `run()` method and/or put the thread back into the thread pool when the application's `run()` method returns. – Stephen C Apr 08 '22 at 05:45
  • If there is any such document, I'm not aware of it. It would most likely be Sun "commercial in confidence" ... and buried deep in some Oracle private archive by now. (If you can't find it with a Google search, forget it. If you haven't Googled it yet, you know what you need to do.) – Stephen C Apr 08 '22 at 05:47
  • There is a small reason to extend `Thread` - as replacement for `ThreadLocal`s. Works because you can cast the result of `Thread.getCurrentThread()` to your own subclass. – Johannes Kuhn Apr 10 '22 at 12:27
1

Java doesn't have multiple inheritance concept for classes ,but for interface it is .

Let's say you have a class which is already extending(inheriting) a class

class A extends Parent{

}

Above class can't extend another class like

class A extends Parent extends Thread{ // Incorrect
    
    }

But it can have something like

class A extends Parent implements Runnable{
    
    }

Now for above case if you want to utillize multi threading ,you can easily do that.

For more look here

Shubham Dixit
  • 9,242
  • 4
  • 27
  • 46
1

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.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
0

Because if we extend Thread class the we can't extend any other class so that reason java provide runnable interface it is higly recomanded to use runnable interface if we implement runnable interface then we can extends any other also

Manoj
  • 37
  • 6
  • 2
    Thanks for your reply but the question is Do we need a Thread class which is overridable , Can that be just used for executing the runnable subclasses ? What is the need to make the Thread class consumable ? – Thaveedu Apr 08 '22 at 05:31