Вопрос: «Реализует Runnable» против «extends Thread»


С какого времени я провел с потоками в Java, я нашел эти два способа писать темы:

С implements Runnable:

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

Или, с extends Thread:

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

Есть ли существенная разница в этих двух блоках кода?


1761


источник


Ответы:


Да: реализует Runnableэто предпочтительный способ сделать это, ИМО. Вы не специализируетесь на поведении потока. Вы просто даете ему что-то бежать. Это значит состав это философски «более чистый» путь.

В практическое термины, это означает, что вы можете реализовать Runnableи простираются и от другого класса.


1423



tl; dr: реализует Runnable лучше. Однако оговорка важна

В общем, я бы рекомендовал использовать что-то вроде Runnableскорее, чем Threadпотому что это позволяет вам поддерживать вашу работу только в сочетании с вашим выбором параллелизма. Например, если вы используете Runnableи позже решите, что на самом деле этого не требуется Thread, вы можете просто вызвать thread.run ().

Предостережение: Вокруг здесь я категорически отвергаю использование необработанных потоков. Я предпочитаю использовать вызываемые объекты а также FutureTasks (Из javadoc: «Анистроинное вычисление с отменой»). Интеграция тайм-аутов, правильная отмена и объединение потоков современной поддержки параллелизма для меня намного полезнее, чем груды необработанных потоков.

Следовать за: Eсть FutureTaskконструктор который позволяет использовать Runnables (если это то, что вам больше всего нравится) и по-прежнему пользоваться преимуществами современных инструментов параллелизма. Чтобы процитировать javadoc:

Если вам не нужен конкретный результат, подумайте об использовании конструкций формы:

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

Итак, если мы заменим их runnableс вашей threadA, получаем следующее:

new FutureTask<Object>(threadA, null)

Другой вариант, который позволяет вам оставаться ближе к Runnables, - это ThreadPoolExecutor , Вы можете использовать выполнять метод передать в Runnable для выполнения «данной задачи когда-нибудь в будущем».

Если вы хотите попробовать использовать пул потоков, фрагмент кода выше будет выглядеть примерно следующим образом (используя Executors.newCachedThreadPool () заводской метод):

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

487



Мораль истории:

Наследовать, только если вы хотите переопределить какое-либо поведение.

Вернее, его следует читать как:

Наследовать меньше, интерфейс больше.


223



Ну так много хороших ответов, я хочу добавить еще об этом. Это поможет понять Extending v/s Implementing Thread,
Extends очень тесно связывает два файла класса и может привести к довольно сложной работе с кодом.

Оба подхода выполняют ту же работу, но были некоторые различия.
Наиболее распространенная разница

  1. Когда вы расширяете класс Thread, после этого вы не можете расширить какой-либо другой класс, который вам нужен. (Как вы знаете, Java не позволяет наследовать более одного класса).
  2. Когда вы реализуете Runnable, вы можете сохранить пространство для своего класса, чтобы расширить любой другой класс в будущем или сейчас.

Однако один значимое различие между реализацией Runnable и продолжением Thread является то, что
by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.

Следующий пример поможет вам более четко понять

//Implement Runnable Interface...
 class ImplementsRunnable implements Runnable {

private int counter = 0;

public void run() {
    counter++;
    System.out.println("ImplementsRunnable : Counter : " + counter);
 }
}

//Extend Thread class...
class ExtendsThread extends Thread {

private int counter = 0;

public void run() {
    counter++;
    System.out.println("ExtendsThread : Counter : " + counter);
 }
}

//Use above classes here in main to understand the differences more clearly...
public class ThreadVsRunnable {

public static void main(String args[]) throws Exception {
    // Multiple threads share the same object.
    ImplementsRunnable rc = new ImplementsRunnable();
    Thread t1 = new Thread(rc);
    t1.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    Thread t2 = new Thread(rc);
    t2.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    Thread t3 = new Thread(rc);
    t3.start();

    // Creating new instance for every thread access.
    ExtendsThread tc1 = new ExtendsThread();
    tc1.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    ExtendsThread tc2 = new ExtendsThread();
    tc2.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    ExtendsThread tc3 = new ExtendsThread();
    tc3.start();
 }
}

Вывод вышеуказанной программы.

ImplementsRunnable : Counter : 1
ImplementsRunnable : Counter : 2
ImplementsRunnable : Counter : 3
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1

В интерфейсе Runnable создается только один экземпляр класса, и он разделяется различными потоками. Таким образом, значение счетчика увеличивается для каждого доступа к потоку.

В то время как подход класса Thread, вы должны создать отдельный экземпляр для каждого доступа к потоку. Следовательно, для каждого экземпляра класса выделяется различная память, и каждый имеет отдельный счетчик, значение остается таким же, что означает, что приращение не произойдет, потому что ни одна из ссылок на объекты не будет такой же.

Когда использовать Runnable?
Используйте интерфейс Runnable, если вы хотите получить доступ к одному и тому же ресурсу из группы потоков. Избегайте использования класса Thread здесь, потому что создание нескольких объектов потребляет больше памяти, и это становится большой служебной нагрузкой.

Класс, который реализует Runnable, не является потоком и просто классом. Чтобы Runnable стал Thread, вам нужно создать экземпляр Thread и передать себя в качестве цели.

В большинстве случаев интерфейс Runnable должен использоваться, если вы только планируете переопределить run()метод и другие методы Thread. Это важно, потому что классы не должны подклассифицироваться, если программист не намерен изменять или улучшать фундаментальное поведение класса.

Когда необходимо расширить суперкласс, реализация интерфейса Runnable более подходит, чем использование класса Thread. Потому что мы можем расширить другой класс, внедряя интерфейс Runnable для создания потока.

Я надеюсь, это поможет!


179



Одна вещь, которую я удивляю, еще не упоминалась, заключается в том, что внедрение Runnableделает ваш класс более гибким.

Если вы увеличиваете поток, то действие, которое вы делаете, всегда будет в потоке. Однако, если вы реализуете Runnableэто не обязательно. Вы можете запустить его в потоке или передать его какой-либо службе-исполнителю или просто передать его как задачу в однопоточном приложении (возможно, для запуска позднее, но в пределах одного потока). Варианты намного более открытые, если вы просто используете Runnableчем если вы привяжете себя к Thread,


72



If you want to implements or extends any other class then Runnable interface is most preferable other wise if you do not want any other class to extend or implement then Thread class is preferable

The most common difference is

enter image description here

When you extends Thread class, after that you can’t extend any other class which you required. (As you know, Java does not allow inheriting more than one class).

When you implements Runnable, you can save a space for your class to extend any other class in future or now.

  • Java doesn't support multiple inheritance, which means you can only extend one class in Java so once you extended Thread class you lost your chance and can not extend or inherit another class in Java.

  • In Object oriented programming extending a class generally means adding new functionality, modifying or improving behaviors. If we are not making any modification on Thread then use Runnable interface instead.

  • Runnable interface represent a Task which can be executed by either plain Thread or Executors or any other means. so logical separation of Task as Runnable than Thread is good design decision.

  • Separating task as Runnable means we can reuse the task and also has liberty to execute it from different means. since you can not restart a Thread once it completes. again Runnable vs Thread for task, Runnable is winner.

  • Java designer recognizes this and that's why Executors accept Runnable as Task and they have worker thread which executes those task.

  • Inheriting all Thread methods are additional overhead just for representing a Task which can be done easily with Runnable.

Courtesy from javarevisited.blogspot.com

These were some of notable difference between Thread and Runnable in Java, if you know any other differences on Thread vs Runnable than please share it via comments. I personally use Runnable over Thread for this scenario and recommends to use Runnable or Callable interface based on your requirement.

However, the significant difference is.

When you extends Thread class, each of your thread creates unique object and associate with it. When you implements Runnable, it shares the same object to multiple threads.


64



Actually, It is not wise to compare Runnable and Thread with each other.

This two have a dependency and relationship in multi-threading just like Wheel and Engine relationship of motor vehicle.

I would say, there is only one way for multi-threading with two steps. Let me make my point.

Runnable:
When implementing interface Runnable it means you are creating something which is run able in a different thread. Now creating something which can run inside a thread (runnable inside a thread), doesn't mean to creating a Thread.
So the class MyRunnable is nothing but a ordinary class with a void run method. And it's objects will be some ordinary objects with only a method run which will execute normally when called. (unless we pass the object in a thread).

Thread:
class Thread, I would say A very special class with the capability of starting a new Thread which actually enables multi-threading through its start() method.

Why not wise to compare?
Because we need both of them for multi-threading.

For Multi-threading we need two things:

  • Something that can run inside a Thread (Runnable).
  • Something That can start a new Thread (Thread).

So technically and theoretically both of them is necessary to start a thread, one will run and one will make it run (Like Wheel and Engine of motor vehicle).

That's why you can not start a thread with MyRunnable you need to pass it to a instance of Thread.

But it is possible to create and run a thread only using class Thread because Class Thread implements Runnable so we all know Thread also is a Runnable inside.

Finally Thread and Runnable are complement to each other for multithreading not competitor or replacement.


60



You should implement Runnable, but if you are running on Java 5 or higher, you should not start it with new Thread but use an ExecutorService instead. For details see: How to implement simple threading in Java.


42