Java для профессионалов: Многопоточность (Threads)

Что такое потоки в Java?

Потоки — это механизм, позволяющий выполнять несколько действий одновременно. Например, можно одновременно скачивать данные из интернета и отображать анимацию прогресса загрузки в статус-баре (от 0 до 100%). В этом случае один поток отвечает за скачивание, а другой — за обновление статус-бара. В играх потоки могут обрабатывать действия игрока, воспроизводить музыку и анимацию. В сущности, потоки обеспечивают распределение задач для параллельного выполнения.

Потоки и многоядерные процессоры

Ранее, когда существовали только одноядерные процессоры, выполнение происходило последовательно. Современные многоядерные процессоры позволяют выполнять несколько действий одновременно. Хотя Java изначально разрабатывался для одноядерных процессоров, он эффективно работает и на многоядерных системах, используя потоки для распределения задач между ядрами. Более современные языки программирования изначально ориентированы на многоядерность, но Java, благодаря потокам, успешно справляется с этой задачей.

Реализация потоков в Java

Существует два способа реализации потоков: наследование от класса Thread и реализация интерфейса Runnable.

Наследование от Thread

Создадим класс MyThread, наследующий от класса Thread:

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(i);
        }
    }
}

Метод run() содержит код, выполняемый в отдельном потоке. Для запуска потока вызываем метод start():

MyThread thread1 = new MyThread();
thread1.start();

Запустив этот код, мы увидим вывод чисел от 0 до 9. Создадим ещё один объект класса MyThread и запустим его:

MyThread thread2 = new MyThread();
thread2.start();

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

Интерфейс Runnable

Второй способ — реализация интерфейса Runnable. Создадим класс MyRunnable, реализующий интерфейс Runnable:

class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(i);
        }
    }
}

Для создания и запуска потока:

MyRunnable runnable1 = new MyRunnable();
Thread thread3 = new Thread(runnable1);
thread3.start();

MyRunnable runnable2 = new MyRunnable();
Thread thread4 = new Thread(runnable2);
thread4.start();

Результат аналогичен предыдущему примеру — параллельное выполнение. Также можно создавать и запускать потоки без создания дополнительных классов, используя анонимные классы или лямбда-выражения:

Thread t1 = new Thread(() -> {
    for (int i = 0; i < 10; i++) {
        System.out.println(i);
    }
});
t1.start();

Потоки — мощный инструмент в Java, позволяющий создавать высокопроизводительные приложения, обрабатывающие множество задач параллельно. Они незаменимы при разработке приложений с параллельными вычислениями, обработкой сетевых запросов и создании игр. Знание работы с потоками является важным навыком для любого Java-разработчика.

Что будем искать? Например,программа