Multithreading в Java: просто о сложном | OTUS
⚡ Открываем подписку на курсы!
Проходите параллельно 3 онлайн-курса в месяц по цене одного.
Подробнее

Курсы

Программирование
Программист 1С Реверс-инжиниринг. Продвинутый курс
-16%
Java Developer. Professional
-17%
JavaScript Developer. Professional
-18%
Flutter Mobile Developer
-15%
JavaScript Developer. Basic
-16%
Highload Architect
-10%
Нереляционные базы данных
-17%
Подготовка к сертификации Oracle Java Programmer (OCAJP)
-8%
Алгоритмы и структуры данных
-12%
Архитектура и шаблоны проектирования
-14%
Framework Laravel
-13%
IoT-разработчик
-12%
Team Lead
-15%
VOIP инженер Разработчик C# Разработчик на Spring Framework AWS для разработчиков Cloud Solution Architecture CI/CD Vue.js разработчик Разработчик Node.js Scala-разработчик Супер - интенсив по Kubernetes Symfony Framework Advanced Fullstack JavaScript developer
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Multithreading в Java: просто о сложном

java_Deep_5-5020-bb8540.10_site.png

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

Начнём с простого

Что такое поток в Java? Как и всё остальное, поток в Java — это объект. Создать объект потока совсем не сложно:

Thread thread = new Thread(); 

Что в этом объекте особенного? У него есть методы start() и run(). Например, если в методе main() вызвать у объекта потока метод start(), то через некоторое время у него будет вызван метод run(). И этот вызов будет иметь новый Stack и команды метода run() могут быть выполнены физически в одно и тоже время, что и команды метода main().

То есть… в другом потоке. И в этом первая сложность многопоточности: поток — это объект и в то же время поток — это последовательность команд. Команд метода run() объекта потока.

Вторая сложность многопоточности в непредсказуемости порядка некоторых событий. Допустим вы создали 10 новых потоков, пронумеровали их и вызвали у них методы start(). Будут ли методы run() этих объектов выполнены в той же последовательности, что вы задали при нумерации?

На самом деле нет. Значит, в какой последовательности будут выполнены методы run(), решает… операционная система. И у вас есть только очень опосредованные способы влияния на порядок выполнения (например, через приоритеты).

Взаимодействие потоков

Если у вас есть задача, которую можно сделать в отдельном потоке, не дожидаясь её завершения и игнорируя её результат (например: записать что-то в лог; послать по UDP данные; обработать запрос пользователя, прочитать ответ в базе и отправить пользователю), то многопоточность — легко и весело.

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

Ошибки приложения, которые при этом происходят, относят к одному из двух типов: race condition и memory consistency errors. Что это, и как с ними бороться, мы рассмотрим чуть позже.

Есть вопрос? Напишите в комментариях!

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться