23

"implements Runnable" против "extends Thread" в Java: что выбрать?

20

Я столкнулся с вопросом о том, как в Java реализовать потоки, и нашел два способа их создания:

  1. С использованием интерфейса Runnable:
public class MyRunnable implements Runnable {
    public void run() {
        // Код потокa
    }
}
// Запускается с помощью вызова "new Thread(new MyRunnable()).start()"
  1. С использованием класса Thread:
public class MyThread extends Thread {
    public MyThread() {
        super("MyThread");
    }
    public void run() {
        // Код потокa
    }
}
// Запускается с помощью вызова "new MyThread().start()"

Возникает вопрос: есть ли какие-либо значительные различия между этими двумя подходами в использовании потоков?

3 ответ(ов)

2

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

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

Или, точнее, это можно понимать так:

Наследуйте реже, используйте интерфейсы чаще.

0

На самом деле, нерационально сравнивать Runnable и Thread друг с другом.

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

Скажу так: для реализации многопоточности существует только один путь, состоящий из двух шагов. Позвольте объяснить свою точку зрения.

Runnable:

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

Таким образом, класс MyRunnable является просто обычным классом с методом void run. Его объекты будут обычными объектами с единственным методом run, который будет выполняться нормально при вызове (если мы не передаем объект в поток).

Thread:

Класс Thread — это, можно сказать, очень специализированный класс, обладающий возможностью запуска нового потока, который фактически обеспечивает многопоточность через свой метод start().

Почему нерационально сравнивать?

Потому что для многопоточности нам нужны оба этих компонента.

Для многопоточности нам нужно два вещи:

  • Что-то, что может выполняться внутри потока (Runnable).
  • Что-то, что может запустить новый поток (Thread).

Таким образом, технически и теоретически оба этих компонента необходимы для запуска потока: один будет выполнять, а другой — запускать (как колесо и двигатель в автомобиле).

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

Но вполне возможно создать и запустить поток, используя только класс Thread, поскольку класс Thread реализует Runnable, так что нам известно, что Thread также является Runnable.

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

0

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

Редактирование: Изначально здесь также упоминалось, что "реализация интерфейса требует меньше ресурсов", но вы всё равно должны создать новый экземпляр класса Thread, так что это было неверно.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь