"implements Runnable" vs "extends Thread" in Java

Viewed 745010

From what time I've spent with threads in Java, I've found these two ways to write threads:

With implements Runnable:

public class MyRunnable implements Runnable {
    public void run() {
        //Code
    }
}
//Started with a "new Thread(new MyRunnable()).start()" call

Or, with extends Thread:

public class MyThread extends Thread {
    public MyThread() {
        super("MyThread");
    }
    public void run() {
        //Code
    }
}
//Started with a "new MyThread().start()" call

Is there any significant difference in these two blocks of code?

43 Answers

Yes: implements Runnable is the preferred way to do it, IMO. You're not really specialising the thread's behaviour. You're just giving it something to run. That means composition is the philosophically "purer" way to go.

In practical terms, it means you can implement Runnable and extend from another class as well... and you can also implement Runnable via a lambda expression as of Java 8.

tl;dr: implements Runnable is better. However, the caveat is important.

In general, I would recommend using something like Runnable rather than Thread because it allows you to keep your work only loosely coupled with your choice of concurrency. For example, if you use a Runnable and decide later on that this doesn't in fact require its own Thread, you can just call threadA.run().

Caveat: Around here, I strongly discourage the use of raw Threads. I much prefer the use of Callables and FutureTasks (From the javadoc: "A cancellable asynchronous computation"). 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.

Follow-up: There is a FutureTask constructor that allows you to use Runnables (if that's what you are most comfortable with) and still get the benefit of the modern concurrency tools. To quote the javadoc:

If you don't need a particular result, consider using constructions of the form:

Future<?> f = new FutureTask<Object>(runnable, null)

So, if we replace their runnable with your threadA, we get the following:

new FutureTask<Object>(threadA, null)

Another option that allows you to stay closer to Runnables is a ThreadPoolExecutor. You can use the execute method to pass in a Runnable to execute "the given task sometime in the future".

If you'd like to try using a thread pool, the code fragment above would become something like the following (using the Executors.newCachedThreadPool() factory method):

ExecutorService es = Executors.newCachedThreadPool();
es.execute(new ThreadA());

Moral of the story:

Inherit only if you want to override some behavior.

Or rather it should be read as:

Inherit less, interface more.

One thing that I'm surprised hasn't been mentioned yet is that implementing Runnable makes your class more flexible.

If you extend thread then the action you're doing is always going to be in a thread. However, if you implement Runnable it doesn't have to be. You can run it in a thread, or pass it to some kind of executor service, or just pass it around as a task within a single threaded application (maybe to be run at a later time, but within the same thread). The options are a lot more open if you just use Runnable than if you bind yourself to Thread.

I'm not an expert, but I can think of one reason to implement Runnable instead of extend Thread: Java only supports single inheritance, so you can only extend one class.

Edit: This originally said "Implementing an interface requires less resources." as well, but you need to create a new Thread instance either way, so this was wrong.

Instantiating an interface gives a cleaner separation between your code and the implementation of threads, so I'd prefer to implement Runnable in this case.

Difference between Extending Thread and Implementing Runnable are:

enter image description here

Separating the Thread class from the Runnable implementation also avoids potential synchronization problems between the thread and the run() method. A separate Runnable generally gives greater flexibility in the way that runnable code is referenced and executed.

Can we re-visit the basic reason we wanted our class to behave as a Thread? There is no reason at all, we just wanted to execute a task, most likely in an asynchronous mode, which precisely means that the execution of the task must branch from our main thread and the main thread if finishes early, may or may not wait for the branched path(task).

If this is the whole purpose, then where do I see the need of a specialized Thread. This can be accomplished by picking up a RAW Thread from the System's Thread Pool and assigning it our task (may be an instance of our class) and that is it.

So let us obey the OOPs concept and write a class of the type we need. There are many ways to do things, doing it in the right way matters.

We need a task, so write a task definition which can be run on a Thread. So use Runnable.

Always remember implements is specially used to impart a behaviour and extends is used to impart a feature/property.

We do not want the thread's property, instead we want our class to behave as a task which can be run.

1. Extending the thread interface, is like you are making your class to behave as a thread only. Your new class will be like a enhanced thread.

jshell> public class Test extends Thread{
   ...> public Test(String name){
   ...> super(name);
   ...> }
   ...> public void run(){
   ...> System.out.println(Thread.currentThread().getName());
   ...> }
   ...> }
|  created class Test

jshell> Test t1=new Test("MyThread");
t1 ==> Thread[MyThread,5,main]

It creates a thread, not the Test object. So it's going to act like a single thread. You can not share the instance of Test class between threads.

2. Implementing the runnable interface.

jshell> public class Test1 implements Runnable{
   ...> public void run(){
   ...> System.out.println(Thread.currentThread().getName());
   ...> }
   ...> public String getName(){
   ...> return "testing";}
   ...> }
|  created class Test1

jshell> Test1 t1=new Test1();
t1 ==> Test1@396a51ab  --> this creates Test1 object.

This object can be shared across threads by,

jshell> Thread t1=new Thread(t1,"Hai");
t ==> Thread[Hai,5,main]

jshell> Thread t=new Thread(t1,"Hai");
t ==> Thread[Hai,5,main]

I think there's already been a lot that's been discussed on this topic, thought this might be helpful around the basics.

Thread class defines several methods that can be overriden by the the extending class. But to create a thread we must override the run() method. Same applies to Runnable as well.

However Runnable is a preferred method of creating a thread. The primary reasons are:

  1. Since Runnable is an interface, you can extend other classes. But if you extend Thread then that option is gone.

  2. If you are not modifying or enhancing a whole lot of Thread functionalities and extending the Thread class is not a preferred way.

I would say actual task is decoupled from the thread. We can pass around the task to Thread, Executor framework etc in case of Runnable, whereas with extending Thread task is coupled with thread object itself. The task isolation cannot be done in case of extending Thread. It's like we burn the task to Thread object just something like IC chip (and more specifically will not get any handle to task).

The main difference between Thread and Runnable is: - Thread is like: Worker (execute Runnable) - Runnable is like: Job (to be executed by Thread)

If you want to separate your concerns like, if you want to create Tasks and it does not matter to you who is the worker working on your task then use Runnable and define your work as a task. Just like when you use executor service, you define tasks in form of Runnable/callable and give them to executor service which will then hold the responsibility of workers.

If you want to create a worker by yourself and assign that worker your task, you want more control over the worker thread then use Thread class.

You can use them jointly

Example :

public class A implements Runnable{

    @Override
    public void run() {


        while(true){
             System.out.println("Class A is running");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }}

    }

}



public class Test {

    public static void main(String[] args) {

        Thread myThread =new Thread(new A());// 1
        myThread.start();
        System.out.println(" executed after thread A");//will never be reached

    }

} 
Related