Каким образом можно создать поток?

- Создать потомка класса Thread и переопределить его метод run();

- Создать объект класса Thread, передав ему в конструкторе экземпляр класса, реализующего интерфейс Runnable. Этот интерфейс содержит метод run(), который будет выполняться в новом потоке. Поток закончит выполнение, когда завершится его метод run().

- Вызвать метод submit() у экземпляра класса, реализующего интерфейс ExecutorService, передав ему в качестве параметра экземпляр класса, реализующего интерфейс Runnable или Callable (содержит метод call(), в котором описывается логика выполнения).



Чем различаются Thread и Runnable?

Thread - это класс, некоторая надстройка над физическим потоком.

Runnable - это интерфейс, представляющий абстракцию над выполняемой задачей.

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



В чём заключается разница между методами start() и run()?

Несмотря на то, что start() вызывает метод run() внутри себя, это не то же самое, что просто вызов run(). Если run() вызывается как обычный метод, то он вызывается в том же потоке и никакой новый поток не запускается, как это происходит в случае, когда вы вызываете метод start().