Многопоточность в Java. Создание потоков с помощью Thread

Создать нить(поток) можно тремя способами:

  • расширяя Thread;
  • реализуя Runnable;
  • расширяя Callable;

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

Мы уже затрагивали создание потоков когда рассматривали PipedOutputStream. И мы помним, что там было два потока и код одного потока выполнялся параллельно коду другого.

Поэтому суть потоков думаю понятна. Параллельное выполнение блоков кода друг другу.


Расширение Thread

Ниже в примере класс MyThread расширяет Thread.

Это значит, что в нем должен быть переопределен метод run.

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

То есть он будет выполняться параллельно другому коду, например тому, в котором выполняется код метода мейн.

Пример программы:

class MyThread extends Thread { @Override public void run() { System.out.println(“run() method “); } } public class ExtendsThread { public static void main(String[] args) { //В отличие от реализации Runnable (разберем //в следующем уроке) для каждого потока класса //расширяющего Thread необходимо создавать новый //объект. Создаются три новых объекта MyThread //как можно увидеть MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); //Теперь с помощью метода start в одном потоке //запускается выполнение метода run у объекта t1, //в другом потоке запускается выполнение метода //run у объекта t2 и в третьем потоке запускается //выполнение метода run у объекта t3. //И ясное дело все эти потоки выполняются //параллельно друг другу. t1.start(); t2.start(); t3.start(); } }

Вывод:

Каждый поток вывел по строке как видим.


Преимущества расширения Thread

Основное преимущество расширения Thread в том, что есть возможность переопределять не только run(), но и другие методы, такие как start().

Пример программы:

class MyThread extends Thread { @Override public void start() { System.out.println(“Overriding a start() method”); super.start(); } @Override public void run() { System.out.println(“run() method “); } } public class ExtendsThread { public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); } }

Вывод:

Как видим, теперь и при вызове start тоже выводиться строка.

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

Интерфейс Runnable в Java

Преимущества Runnable над Thread: экономия памяти, гибкость кода и поддержка многопоточности. Пример реализации и сравнение подходов.

Time to read: 10

Volatile переменная в Java

Разберитесь с ключевым словом volatile в Java: как оно обеспечивает видимость изменений переменной для всех потоков. Практический пример использования.

Time to read: 9

Метод join в Java

Узнайте, как метод join() в Java приостанавливает текущий поток до завершения другого. Примеры кода и объяснение работы с потоками для эффективной синхронизации.

Time to read: 11