JavaRush /Курсы /JAVA 25 SELF /Введение в многопоточность: зачем нужна

Введение в многопоточность: зачем нужна

JAVA 25 SELF
51 уровень , 0 лекция
Открыта

1. Что такое поток исполнения (thread)

Поток как самостоятельная линия работы

В Java (и в программировании вообще) поток исполнения — это независимая последовательность команд, которая идёт параллельно с другими потоками внутри одной программы. Представьте фабрику: у каждой швеи свой рабочий стол и задание, она работает независимо, но всё вместе идёт в общий результат.

По умолчанию Java-программа стартует с одного потока — того, что запускает метод main. Но ничто не мешает нам создавать дополнительные потоки, чтобы разные части программы выполнялись одновременно.

Процессы и потоки: в чём разница?

  • Процесс — это «тяжеловесная» единица выполнения. У каждого процесса своя область памяти, свои переменные, свои ресурсы. Процессы полностью изолированы друг от друга — если один «сломается», остальные не пострадают.
  • Поток (thread) — это «легковесная» единица выполнения внутри процесса. Все потоки одного процесса разделяют память и ресурсы. Это значит, что они могут легко обмениваться данными (и, увы, могут легко друг другу мешать).

Аналогия:
Процесс — это отдельная квартира: у каждой свои стены и жильцы.
Потоки — это жильцы внутри одной квартиры: у каждого свои дела, но кухня и ванная общие.

Как это выглядит в Java?

Когда вы запускаете программу, JVM создаёт хотя бы один поток — главный (main). Но вы можете создавать новые потоки, чтобы выполнять задачи параллельно.

2. Зачем нужна многопоточность

Реактивность: UI не должен «зависать»

Допустим, вы пишете графическую программу — например, текстовый редактор. Пользователь нажал кнопку «Сохранить», а вы пошли долго и нудно записывать файл на диск. Если всё это делать в главном потоке, окно программы «замёрзнет»: пользователь не сможет ничего нажать, курсор не двигается, интерфейс не реагирует. Если же сохранить файл в отдельном потоке — интерфейс останется отзывчивым, и пользователь даже сможет передумать и закрыть программу.

Жизненный пример:
Вы открыли браузер и начали скачивать большой файл. Если бы браузер не использовал потоки, вы бы не смогли ни открыть новую вкладку, ни прокрутить страницу, пока файл не скачается!

Параллельная обработка данных

Допустим, у вас есть список из тысячи файлов, которые надо обработать (например, пересчитать хэши или заменить текст). Почему бы не обработать их параллельно? Каждый поток берёт свой файл и работает с ним независимо, и вся работа завершается в несколько раз быстрее.

Пример:
Сервер обрабатывает запросы от сотен клиентов. Если бы сервер делал это в одном потоке, остальные клиенты ждали бы своей очереди вечно. А с потоками каждый запрос обрабатывается независимо!

Использование многоядерных процессоров

Современные процессоры — это не один «мозг», а целая команда (ядра), которые могут работать параллельно. Если ваша программа использует только один поток, остальные ядра скучают и играют в сапёра. Если же вы запускаете несколько потоков — все ядра заняты делом, а программа выполняется быстрее.

Интересный факт:
Даже ваш телефон имеет несколько ядер, а ноутбуки и серверы — десятки! Не использовать их все — всё равно что купить автобус и ездить на нём в одиночку.

3. Примеры из жизни

Сфера Пример многопоточности
Загрузка файлов Скачивание нескольких файлов одновременно
Пользовательский UI Приложение не «зависает» при загрузке/сохранении данных
Серверы Обработка множества сетевых запросов параллельно
Игры Отдельные потоки для физики, графики, музыки, AI
Мессенджеры Получение сообщений, отправка файлов, обновление интерфейса
Видеообработка Обработка кадров параллельно

Мини-аналогия:
Повар готовит суп, а параллельно духовка печёт пирог, а робот-пылесос убирает пол — всё это происходит одновременно, и ужин готовится быстрее!

4. Потенциальные сложности многопоточности

Состояние гонки (race condition)
Когда несколько потоков одновременно меняют одну и ту же переменную, результат может быть непредсказуемым. Например, если два потока одновременно увеличивают общий счётчик, итоговое значение может быть неверным. Об этом подробнее поговорим в одной из следующих лекций.

Синхронизация
Чтобы потоки не мешали друг другу, приходится придумывать способы «договориться» — кто когда может менять данные. Это называется синхронизация. Для этого есть специальные ключевые слова и конструкции (synchronized, блокировки и т.д.), о которых мы поговорим позже.

Deadlock (взаимная блокировка)
Иногда потоки могут так «подружиться», что будут ждать друг друга вечно, и программа зависнет. Это называется deadlock — и это одна из самых коварных ошибок в многопоточном программировании.

Отладка и тестирование
Ошибки в многопоточных программах очень сложно ловить: иногда всё работает, иногда — нет. Иногда баг проявляется только на сервере или у пользователя, а у вас на компьютере всё идеально. Это делает тестирование и отладку многопоточного кода настоящим квестом для разработчика.

5. Краткий обзор: как выглядит многопоточная программа

Пример без потоков:

public class Main {
    public static void main(String[] args) {
        // Считаем до 5
        for (int i = 1; i <= 5; i++) {
            System.out.println(i);
        }
        // Выводим буквы
        for (char c = 'A'; c <= 'E'; c++) {
            System.out.println(c);
        }
    }
}

Вывод всегда одинаковый:

1
2
3
4
5
A
B
C
D
E

Пример с потоками:

public class Main {
    public static void main(String[] args) {
        Thread numbers = new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.println(i);
                try {
                    Thread.sleep(100); // Немного подождём
                } catch (InterruptedException e) {
                    // Игнорируем
                }
            }
        });

        Thread letters = new Thread(() -> {
            for (char c = 'A'; c <= 'E'; c++) {
                System.out.println(c);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // Игнорируем
                }
            }
        });

        numbers.start();
        letters.start();
    }
}

Вывод будет перемешан:

1
A
2
B
3
C
4
D
5
E

или, если потоки «соревнуются», может быть другой порядок. Главное — оба цикла идут параллельно!

6. Полезные нюансы

Визуальная схема: как потоки работают вместе

+-------------------+     +-------------------+
|   Главный поток   |     |   Второй поток    |
+-------------------+     +-------------------+
| 1 | 2 | 3 | 4 | 5 |     | A | B | C | D | E |
+-------------------+     +-------------------+
        |                         |
        |      Оба работают       |
        |      одновременно       |
        +-------------------------+

Где Java использует потоки «под капотом»

  • Сборка мусора (Garbage Collector) — отдельный поток очищает неиспользуемые объекты.
  • Потоки ввода-вывода (IO) — чтение и запись файлов, сетевые соединения.
  • Серверы и веб-приложения — каждый клиентский запрос обрабатывается в отдельном потоке.
  • Таймеры, планировщики задач — выполнение задач по расписанию.

7. Типичные ошибки новичков

Ошибка №1: Ожидание, что потоки всегда ускоряют программу.
На самом деле, если у вас однопроцессорная машина или вы неправильно организовали работу, многопоточность может только замедлить выполнение из-за «путаницы» и накладных расходов на переключение между потоками.

Ошибка №2: Игнорирование проблем синхронизации.
Многие уверены: «Я же просто запускаю два потока, чего тут может пойти не так?» Но если оба потока меняют одну переменную, результат может быть абсолютно неожиданным.

Ошибка №3: Использование потоков для всего подряд.
Не стоит запускать отдельный поток для каждого чиха. Потоки — это ресурс, и их чрезмерное количество может привести к тормозам и даже к краху программы.

Ошибка №4: Отсутствие обработки ошибок.
Потоки могут выбрасывать исключения (например, при работе с файлами или сетью). Если не обрабатывать эти ошибки, программа может завершиться аварийно или «зависнуть».

1
Задача
JAVA 25 SELF, 51 уровень, 0 лекция
Недоступна
Выявление главного героя программы 🕵️‍♀️
Выявление главного героя программы 🕵️‍♀️
1
Задача
JAVA 25 SELF, 51 уровень, 0 лекция
Недоступна
Инструкции для робота-помощника 🤖
Инструкции для робота-помощника 🤖
Комментарии (2)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Andrey Уровень 1
18 октября 2025
51+
I'll kick them all Уровень 5
13 октября 2025
51