Многозадачность
Многозадачность — это способность операционной системы одновременно выполнять несколько программ.
Она позволяет пользователю работать с несколькими приложениями, например, слушать музыку, писать текст и просматривать интернет одновременно. Операционная система управляет ресурсами компьютера, чтобы каждая программа могла получать необходимое время и память для работы. Это делает использование компьютера более удобным и эффективным.
Без многозадачности пользователь мог бы запускать только одно приложение за раз. Например, если мы слушаем музыку,то смогли бы одновременно просматривать новости в интернете — для этого пришлось бы закрывать одно приложение, чтобы открыть другое. Это сделало бы использование компьютера менее удобным и эффективным
Многозадачность не является свойством языка программирования Java, а является функцией операционной системы. Язык Java может использовать многозадачность через потоки, которые создаются на основе системных потоков операционной системы для выполнения нескольких задач одновременно. Java предоставляет API для создания и управления этими потоками, но сама операционная система управляет их выполнением и ресурсами. Таким образом, многозадачность является фундаментальной функцией операционной системы, которая позволяет языкам программирования, таким как Java, создавать более эффективные и удобные приложения
Многопоточность
Многопоточность — это возможность программы выполнять несколько задач одновременно, используя так называемые потоки. Поток — это отдельная часть программы, которая может работать параллельно с другими потоками.
Многопоточность и многозадачность
Многозадачность и многопоточность - это два понятия, которые часто путают друг с другом, но они имеют разные значения, работают на разных уровнях. Многозадачность касается управления несколькими программами на уровне операционной системы. Например, вы открываете браузер и текстовый редактор, одновременно набираете текст и слушаете музыку. Многопоточность позволяет выполнять несколько задач внутри одной программы. Например, браузер загружает данные из интернета и одновременно отображает информацию на экране, не дожидаясь завершения загрузки.
Таким образом основная разница между многозадачностью и многопоточностью заключается в том, что многозадачность относится к выполнению нескольких программ или процессов одновременно, а многопоточность относится к выполнению нескольких задач или потоков внутри одной программы или процесса.
По-настоящему параллельное выполнение задач возможно только в многоядерной системе, поскольку только в них присутствуют несколько системных конвейеров для исполнения команд. В одноядерной многозадачной системе поддерживается так называемое псевдопараллельное исполнение, при котором создается видимость параллельной работы нескольких процессов. В таких системах процессы выполняются последовательно, занимая малые кванты процессорного времени.
Возможности многопоточности
Многопоточность - это мощный инструмент, который широко используется в приложениях с пользовательским интерфейсом. Основная идея многопоточности заключается в том, чтобы разделить задачи на несколько потоков, что позволяет выполнять несколько задач одновременно. Это особенно полезно в приложениях, где за работу интерфейса отвечает один поток, а какие-либо вычисления выполняются в других потоках.
Таким образом, пользовательский интерфейс не подвисает, когда приложение занято другими вычислениями. Например, если вы открываете текстовый редактор и начинаете набирать текст, редактор может выполнять другие задачи, такие как проверка орфографии или автосохранение документа, в отдельных потоках. Это позволяет интерфейсу редактора оставаться отзывчивым и не подвисать.
Многопоточность также полезна, когда алгоритмы можно разбить на независимые подзадачи, которые можно выполнять в разных потоках. Например, при фильтрации изображения разные потоки могут заниматься фильтрацией разных частей изображения. Это позволяет повысить производительность и ускорить выполнение задач.
Кроме того, многопоточность полезна, когда некоторые части приложения вынуждены ждать ответа от сервера, пользователя или устройства. В этом случае эти операции можно выделить в отдельный поток, чтобы в основном потоке можно было продолжать работу, пока другой поток ждёт ответа. Это позволяет приложению оставаться отзывчивым, даже если некоторые операции требуют времени для выполнения.
Процесс и поток
Процесс и поток — это два ключевых понятия в области операционных систем, которые относятся к выполнению программ
Процесс — это экземпляр выполняемой программы. Он включает в себя не только код программы, но и все необходимые ресурсы для её выполнения, такие как память, открытые файлы и состояние выполнения, кроме процесорного времени. Каждый процесс имеет свою собственную область памяти, что обеспечивает изоляцию между процессами. Это значит, что один процесс не может напрямую обращаться к памяти другого процесса, что помогает предотвратить ошибки и конфликты.
Поток — это наименьшая единица выполнения в рамках процесса. Каждый процесс может содержать один или несколько потоков. Потоки внутри одного процесса разделяют общую память и ресурсы, что позволяет им взаимодействовать друг с другом более эффективно. Это делает потоки легче и быстрее в создании и управлении по сравнению с процессами.
Разница между процессом и потоком заключается в том, что процесс — это способ организовать все необходимые ресурсы для выполнения программы, а потоки — это единицы выполнения, которые используют процессорное время для выполнения конкретных задач. Таким образом, процессы организуют ресурсы, а потоки выполняют работу.
Потоки легче создавать и управлять, так как они используют общие ресурсы процесса. Потоки могут легко обмениваться данными и взаимодействовать друг с другом, так как они работают в одной области памяти.
Состояние потоков
Потоки в операционной системе могут находиться в различных состояниях в зависимости от того, что они делают в данный момент. Эти состояния помогают управлять выполнением потоков и оптимизировать использование ресурсов процессора. Вот основные состояния потока:
- Выполняемый (Executing) - поток, который выполняется в текущий момент на процессоре.
- Готовый (Runnable) - поток ждет получения кванта времени и готов выполнять назначенные ему инструкции. Планировщик выбирает следующий поток для выполнения только из готовых потоков.
- Ожидающий (Waiting) - работа потока заблокирована в ожидании блокирующей операции.
Проблемы многопоточности
Многопоточность может значительно повысить производительность и отзывчивость приложений, но она также может привести к различным проблемам, которые затрудняют разработку и отладку. Вот некоторые из основных проблем, с которыми могут столкнуться разработчики при работе с многопоточными системами
Состояние гонки
Состояние гонки — это ошибка проектирования многопоточной системы или приложения, при которой результат работы системы зависит от порядка выполнения различных частей кода. Это происходит, когда несколько потоков одновременно пытаются изменить одну и ту же переменную или ресурс без должной синхронизации. В результате, если порядок выполнения потоков изменится, это может привести к непредсказуемым и ошибочным результатам, что делает систему нестабильной и трудной для отладки.
Это наш разделяемый ресурс
Два потока пытаются изменить наш разделяемый ресурс без синхронизации. Например, поток 1 считывает текущее значение counter, а затем поток 2 также считывает это значение до того, как поток 1 успевает его обновить, оба потока могут записать одно и то же значение, что приводит к потере инкремента.
В результате, при каждом запуске программы значение счетчика, выводимое на экран, будет разным и, как правило, не будет равно ожидаемому значению 20000
Deadlock
Deadlock (взаимная блокировка) — это ситуация, при которой несколько потоков находятся в состоянии ожидания ресурсов, занятых друг другом, и ни один из них не может продолжать выполнение. Например, поток A может удерживать ресурс 1 и ожидать ресурс 2, в то время как поток B удерживает ресурс 2 и ожидает ресурс 1. В результате оба потока застревают, и система не может продолжать работу, что приводит к потере производительности и необходимости ручного вмешательства для разрешения ситуации
Голодание потоков
Голодание потоков — это ситуация, в которой поток не может получить доступ к общим ресурсам, потому что на эти ресурсы всегда претендуют другие потоки, которым отдается предпочтение. Это может произойти, если планировщик потоков неравномерно распределяет процессорное время или если некоторые потоки имеют более высокий приоритет. В результате, потоки с низким приоритетом могут никогда не получить возможность выполнить свою работу
Класс потока
<!DOCTYPE html>
<html class="h-100" data-bs-theme="light" data-mantine-color-scheme="light" lang="ru" prefix="og: https://ogp.me/ns#">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<link crossorigin="true" href="https://cdn.hexlet.io" rel="preconnect">
<link href="https://mc.yandex.ru" rel="preconnect">
<meta content="aa2vrdtq64dub8knuf83lwywit311w" name="facebook-domain-verification">
<link href="/favicon.ico" rel="icon" sizes="any">
<link href="/favicon.svg" rel="icon" type="image/svg+xml">
<link href="/apple-touch-icon.png" rel="apple-touch-icon">
<link href="/manifest.webmanifest" rel="manifest">
<script>
//<![CDATA[
window.gon={};gon.ym_counter="25559621";gon.is_bot=true;gon.applications={};gon.current_user={"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26 16:37:45 UTC","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false};gon.token="ZBhijpQOGT-8JHM2ZVBhwTltdT-Xe-iuLoof9hXi9BGLyam5ZnC0XwpnV65pX5G2-WRYlZ9MFgyTaoWiR-UTfw";gon.locale="ru";gon.language="ru";gon.theme="light";gon.rails_env="production";gon.mobile=false;gon.google={"analytics_key":"UA-1360700-51","optimize_key":"GTM-5QDVFPF"};gon.captcha={"google_v3_site_key":"6LenGbgZAAAAAM7HbrDbn5JlizCSzPcS767c9vaY","yandex_site_key":"ysc1_Vyob5ZPPUdPBsu0ykt8bVFdzsfpoVjQChLGl2b4g19647a89","verification_failed":null};gon.social_signin=false;gon.typoreporter_google_form_id="1FAIpQLSeibfGq-KvWQ2Fyru-zkFFRVTLBuzXAHAoEyN1p49FtDmNoNA";
//]]>
</script>
<meta charset="utf-8">
<title>Многопоточность | Java: Продвинутое использование</title>
<meta name="description" content="Многопоточность / Java: Продвинутое использование: Выясняем, что такое многопоточность">
<link rel="canonical" href="https://ru.hexlet.io/courses/java-advanced/lessons/multithreading/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="Многопоточность">
<meta property="og:title" content="Java: Продвинутое использование">
<meta property="og:description" content="Многопоточность / Java: Продвинутое использование: Выясняем, что такое многопоточность">
<meta property="og:url" content="https://ru.hexlet.io/courses/java-advanced/lessons/multithreading/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="kpFc2NBRFtKHyqDYGplvGWS9zElzVt4MCXAleM_4Ykh9QJfvIi-7sjGJhEAWlp9upLTh43thIK60kL8snf-FJg" />
<script src="/vite/assets/inertia-INZxX8jp.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/preload-helper-BJ4cLWpC.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-nkZBEvfU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ahoy-DrlRQ-1D.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/analytics-6pOtQ3OW.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Surface-DL2bpZA-.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/extends-C-EagtpE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/inheritsLoose-BBd-DCVI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/objectWithoutPropertiesLoose-DRHXDhjp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/index.esm-DAqKOkZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Button-CGPUux8l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/CloseButton-D1euiPao.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Group-BX48WcuU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Loader-BQEY8g6v.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Modal-Cy3HByv7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/OptionalPortal-1Hza5P2w.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Stack-CtjJzfw4.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Textarea-Ck64llAy.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/DirectionProvider-Dc9zdUke.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/events-DJQOhap0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-reduced-motion-D2owz4wa.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-disclosure-zKtK5W1r.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-hotkeys-Cnc_Rwkb.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/random-id-DOQyszCZ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/exports-C_MrNx_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<link rel="stylesheet" href="/vite/assets/application-BqhCP46M.js" />
<script src="/vite/assets/application-Df9RExpe.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/autocomplete-VMNbxKGl.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/createPopper-C3aM9r1M.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/js.cookie-D1-O8zkX.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="/vite/assets/application-C8HjmMaq.css" media="screen" />
<script>
window.ym = function(){(ym.a=ym.a||[]).push(arguments)};
window.addEventListener('load', function() {
setTimeout(function() {
ym.l = 1*new Date();
ym(window.gon.ym_counter, "init", {
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
});
// Загружаем скрипт
var k = document.createElement('script');
k.async = 1;
k.src = 'https://mc.yandex.ru/metrika/tag.js';
document.head.appendChild(k);
ym(window.gon.ym_counter, 'getClientID', function(clientID) {
window.ymClientId = clientID;
});
}, 1500);
});
</script>
<!-- Google Tag Manager - deferred -->
<script>
// dataLayer stub сразу — пуши работают до загрузки скрипта
window.dataLayer = window.dataLayer || [];
// Сам скрипт — отложенно после load
window.addEventListener('load', function() {
setTimeout(function() {
dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var j = document.createElement('script');
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-WK88TH';
document.head.appendChild(j);
}, 1500);
});
</script>
<!-- End Google Tag Manager -->
</head>
<body>
<noscript>
<div>
<img alt="" src="https://mc.yandex.ru/watch/25559621" style="position:absolute; left:-9999px;">
</div>
</noscript>
<header class="sticky-top bg-body">
<nav class="navbar navbar-expand-lg">
<div class="container-xxl">
<a class="navbar-brand" href="/"><img alt="Логотип Хекслета" height="24" src="https://ru.hexlet.io/vite/assets/logo_ru_light-BpiEA1LT.svg" width="96">
</a><button aria-controls="collapsable" aria-expanded="false" aria-label="Меню" class="navbar-toggler border-0 mb-0 mt-1" data-bs-target="#collapsable" data-bs-toggle="collapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsable">
<ul class="navbar-nav mb-lg-0 mt-lg-1">
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
Все курсы
<span class="bi bi-chevron-down align-middle ms-1"></span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item d-flex py-2" href="/courses"><div class="fw-bold me-auto">Все что есть</div>
<div class="text-muted">117</div>
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные категории</b>
</li>
<li>
<a class="dropdown-item py-2" href="/courses_devops">Курсы по DevOps
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_data_analytics">Курсы по аналитике данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_programming">Курсы по программированию
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_testing">Курсы по тестированию
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные курсы</b>
</li>
<li>
<a class="dropdown-item py-2" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/go">Go-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/java">Java-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/python">Python-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/qa-auto-engineer-java">Автоматизатор тестирования на Java
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/data-analytics">Аналитик данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/frontend">Фронтенд-разработчик
</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
О Хекслете
<span class="bi bi-chevron-down align-middle"></span>
</button>
<ul class="dropdown-menu bg-body">
<li>
<a class="dropdown-item py-2" href="/pages/about">О нас
</a></li>
<li>
<a class="dropdown-item py-2" href="/blog">Блог
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/hse-research" role="button">Результаты (Исследование)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://career.hexlet.io" role="button">Хекслет Карьера
</span></li>
<li>
<a class="dropdown-item py-2" href="/testimonials">Отзывы студентов
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://t.me/hexlet_help_bot" role="button">Поддержка (В ТГ)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/referal-program/?promo_creative=priglasite-druzei&promo_name=referal-program&promo_position=promo_position&promo_start=010724&promo_type=link" role="button">Реферальная программа
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/certificate" role="button">Подарочные сертификаты
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://hh.ru/employer/4307094" role="button">Вакансии
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://b2b.hexlet.io" data-target="_blank" role="button">Компаниям
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexly.ru/" data-target="_blank" role="button">Колледж
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexlyschool.ru/" data-target="_blank" role="button">Частная школа
</span></li>
</ul>
</li>
<li><a class="nav-link" href="/subscription/new">Подписка</a></li>
</ul>
<ul class="navbar-nav flex-lg-row align-items-lg-center gap-2 ms-auto">
<li>
<a class="nav-link" aria-label="Переключить тему" href="/theme/switch?new_theme=dark"><span aria-hidden="true" class="bi bi-moon"></span>
</a></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="/u/new" role="button"><span>Регистрация</span>
</span></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="https://ru.hexlet.io/session/new" role="button"><span>Вход</span>
</span></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="x-container-xxxl">
</div>
<main class="mb-6 min-vh-100 h-100">
<link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzczNSwicHVyIjoiYmxvYl9pZCJ9fQ==--883f3fd4e1b571538035b5680c8d4a9eb504b1f6/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Source%20code-amico.png"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NTIxOSwicHVyIjoiYmxvYl9pZCJ9fQ==--e79a18f1e9f90eae650f1f4f04115cba51f4e650/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-amico.png"/><link rel="preload" as="image" href="/vite/assets/development-BVihs_d5.png"/><div id="app" data-page="{"component":"web/courses/lessons/theory_unit","props":{"errors":{},"locale":"ru","language":"ru","httpsHost":"https://ru.hexlet.io","host":"ru.hexlet.io","colorScheme":"light","auth":{"user":{"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26T16:37:44.881Z","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false}},"cloudflareTurnstileSiteKey":"0x4AAAAAAA15KmeFXzd2H0Xo","vkIdClientId":"51586979","yandexIdClientId":"88d071f1d3384eb4bd1deb37910235c7","formAuthToken":"ZwMNoM0fI8pwbij6Bd_VVwFcBfnNtSxfQCR51EXAMWmI0saXP2GOqsYtDGIJ0CUgwVUoU8WC0v39xOOAF8fWBw","topics":[{"id":81790,"title":"Добрый день! А что должен делать код из примера?\nУ меня он просто выводит в консоль, что оба потока дошли до 10.000\n\nthread-2:10000\nthread-1:10000","plain_title":"Добрый день! А что должен делать код из примера? У меня он просто выводит в консоль, что оба потока дошли до 10.000 thread-2:10000 thread-1:10000 ","creator":{"public_name":"Евгений Прохоров","id":408048,"is_tutor":false},"comments":[{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":167023,"body":"Приветствую, Евгений! Я немного изменил пример кода в уроке, чтобы можно было лучше отследить состояние гонки, о котором идет речь в конце лекции. Попробуйте поэкспериментировать с этим примером ","topic_id":81790},{"creator":{"public_name":"Anastasiya kondratova","id":555078,"is_tutor":false},"id":179534,"body":"Добрый день. Ввиду того, что пример под видео отличается от примера в видео, не понятно, почему же работает именно так. Ведь мы не устанавливаем ограничение именно на величину счетчика. Объясните, пожалуйста. \n\n> // Значение счетчика каждый запуск будет разным\n // Практически никогда оно не будет равно 20000","topic_id":81790},{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":179565,"body":"Добрый день! Этот пример как раз демонстрируется состояние гонки. Два потока одновременно обращаются к одному и тому же ресурсу. Дело в том, что операция инкремента не атомарна и состоит из нескольких действий. Нужно прочитать значение, изменить его, записать измененное значение. Пока один поток читает значение, воторой может уже изменить значение и так далее. Поэтому в итоге после 20 тысяч итераций значение счечтика почти никогда не будет равно 20 000","topic_id":81790}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Многопоточность","entity_url":null,"active":true}},{"id":81604,"title":"```\n` Post job cleanup.\nHttpClientError: Invalid params\n at HttpClient.<anonymous> (file:///home/runner/work/_actions/hexlet/assignment-action/release/dist/run-post-actions/index.js:2:38387)\n at Generator.next (<anonymous>)\n at fulfilled (file:///home/runner/work/_actions/hexlet/assignment-action/release/dist/run-post-actions/index.js:2:27914)`\n```\n\nОшибка при проверке д/з. В чем проблема может быть?","plain_title":"` Post job cleanup. HttpClientError: Invalid params at HttpClient.<anonymous> (file:///home/runner/work/_actions/hexlet/assignment-action/release/dist/run-post-actions/index.js:2:38387) at Generator.next (<anonymous>) at fulfilled (file:///home/runner/work/_actions/hexlet/assignment-action/release/dist/run-post-actions/index.js:2:27914)` Ошибка при проверке д/з. В чем проблема может быть? ","creator":{"public_name":"Ilnaz Kamalov","id":448293,"is_tutor":false},"comments":[{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":166819,"body":"Добрый день! Приношу извинения за неудобства, поправили этот момент. Нужно сейчас перезапустить на гитхабе упавшую сборку","topic_id":81604}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Многопоточность","entity_url":null,"active":true}},{"id":88493,"title":"\nкоманда hexlet assignment submit не рабоатет из директории дз ~/Hexlet/hexlet-assignments/java-advanced-ru/multithreading$\n\nпишет: Submit assignment (must be called from the assignment directory)\nTypeError: Cannot read properties of null (reading 'length')\n at GitRefManager.expand (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/node_modules/@hexlet/cli/node_modules/isomorphic-git/index.cjs:1982:13)\n at _merge (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/node_modules/@hexlet/cli/node_modules/isomorphic-git/index.cjs:9155:32)\n at async _pull (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/node_modules/@hexlet/cli/node_modules/isomorphic-git/index.cjs:9355:5)\n at async Object.pull (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/node_modules/@hexlet/cli/node_modules/isomorphic-git/index.cjs:11751:12)\n at async gitPull (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/node_modules/@hexlet/cli/src/utils/git.js:28:3)\n at async Object.gitPullMerge [as pullMerge] (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/node_modules/@hexlet/cli/src/utils/git.js:59:5)\n at async module.exports [as handler] (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/node_modules/@hexlet/cli/src/handlers/assignment/submit.js:33:3) { \n caller: 'git.pull'\n}\n\nрепозиторий создался с ним всё ок. в чем может быть дело?","plain_title":"команда hexlet assignment submit не рабоатет из директории дз ~/Hexlet/hexlet-assignments/java-advanced-ru/multithreading$ пишет: Submit assignment (must be called from the assignment directory) TypeError: Cannot read properties of null (reading 'length') at GitRefManager.expand (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/nodemodules/@hexlet/cli/nodemodules/isomorphic-git/index.cjs:1982:13) at merge (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/nodemodules/@hexlet/cli/nodemodules/isomorphic-git/index.cjs:9155:32) at async _pull (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/nodemodules/@hexlet/cli/nodemodules/isomorphic-git/index.cjs:9355:5) at async Object.pull (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/nodemodules/@hexlet/cli/nodemodules/isomorphic-git/index.cjs:11751:12) at async gitPull (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/nodemodules/@hexlet/cli/src/utils/git.js:28:3) at async Object.gitPullMerge as pullMerge (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/node_modules/@hexlet/cli/src/utils/git.js:59:5) at async module.exports as handler (/home/kanarihimawari/.asdf/installs/nodejs/20.2.0/lib/node_modules/@hexlet/cli/src/handlers/assignment/submit.js:33:3) { caller: 'git.pull' } репозиторий создался с ним всё ок. в чем может быть дело? ","creator":{"public_name":"Виктория","id":648556,"is_tutor":false},"comments":[{"creator":{"public_name":"Виктория","id":648556,"is_tutor":false},"id":176691,"body":"https://github.com/tori-p147/hexlet-assignments\n2.2.3","topic_id":88493},{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":176693,"body":"Виктория, репозиторий совершенно пустой. После инициализации там должно было появиться ридми и директория с файлами воркфлоу. Попробуйте заново сделать инициализацию. Обратите пожалуйста внимание, не возникло ли каких-либо ошибок в консоли при ините","topic_id":88493},{"creator":{"public_name":"Виктория","id":648556,"is_tutor":false},"id":176759,"body":"спасибо, переустановила помогло.\nтеперь проблема с грейдлом - он уходит в вечный билд.\nу меня виндус, скачала грейдл на wsl, когда я указываю \"local instalation distribution\" она не сохраняется и пишет gradle location unknown. gradle jvm выбрана 17(WSL)","topic_id":88493},{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":176689,"body":"Приветствую, Виктория! А можете пожалуйста скинуть ссылку на создавшийся репозиторий? Скажите еще пожалуйста, какая у вас версия утилиты hexlet?","topic_id":88493}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Многопоточность","entity_url":null,"active":true}},{"id":81099,"title":"ссылки 404","plain_title":"ссылки 404 ","creator":{"public_name":"Almaz Salyakhov","id":325099,"is_tutor":false},"comments":[{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":165981,"body":"Спасибо, поправил! Вот правильная ссылка https://replit.com/new/bash","topic_id":81099}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Многопоточность","entity_url":null,"active":true}},{"id":81104,"title":"ошибка при сдаче домашки\n```Post job cleanup.\nHttpClientError: Invalid params\n at HttpClient.<anonymous> (file:///home/runner/work/_actions/hexlet/assignment-action/release/dist/run-post-actions/index.js:2:38387)\n at Generator.next (<anonymous>)\n at fulfilled (file:///home/runner/work/_actions/hexlet/assignment-action/release/dist/run-post-actions/index.js:2:27914)```","plain_title":"ошибка при сдаче домашки Post job cleanup. HttpClientError: Invalid params at HttpClient.<anonymous> (file:///home/runner/work/_actions/hexlet/assignment-action/release/dist/run-post-actions/index.js:2:38387) at Generator.next (<anonymous>) at fulfilled (file:///home/runner/work/_actions/hexlet/assignment-action/release/dist/run-post-actions/index.js:2:27914) ","creator":{"public_name":"Almaz Salyakhov","id":325099,"is_tutor":false},"comments":[{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":166059,"body":"Алмаз, попробуйте еще раз отправить домашку на проверку. Возможно в этот момент были какие-то проблемы с сетью","topic_id":81104}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Многопоточность","entity_url":null,"active":true}},{"id":90042,"title":"> Если максимальное количество одновременно запущенных работ не указывать, по умолчанию оно будет равно количеству ядер процессора.\n\nЧуть подушню: видимо, для современных процессоров равно все-таки не количеству ядер, а количеству потоков. У меня 8 ядер \\ 16 потоков, и судя по выводу терминала, именно 16 параллелей страртануло.","plain_title":"Если максимальное количество одновременно запущенных работ не указывать, по умолчанию оно будет равно количеству ядер процессора. Чуть подушню: видимо, для современных процессоров равно все-таки не количеству ядер, а количеству потоков. У меня 8 ядер \\ 16 потоков, и судя по выводу терминала, именно 16 параллелей страртануло. ","creator":{"public_name":"Денис Брагин","id":497216,"is_tutor":false},"comments":[{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":178986,"body":"Хм, в [документации](https://www.gnu.org/software/parallel/parallel_tutorial.html#controlling-the-execution) речь именно о ядрах:\n\n> By default --jobs is the same as the number of CPU cores.\n","topic_id":90042}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Многопоточность","entity_url":null,"active":true}},{"id":99151,"title":"Почему бы не вырезать натурально 20 минут, где г-н Яковлев пытается настроить рабочий пример для лекции(который указан ниже в теории и который, я уверен, можно и необходимо было бы подготовить заранее к лекции, а не кодить в лайв-режиме)?\nМне от этой лекции захотелось уснуть и после 20 минут попыток что-то настроить и показать, пропала вся нить повествования, если убрать это и оставить только удачную попытку, уверен эффект обучения будет лучше. \n\\+ сэкономленное время ","plain_title":"Почему бы не вырезать натурально 20 минут, где г-н Яковлев пытается настроить рабочий пример для лекции(который указан ниже в теории и который, я уверен, можно и необходимо было бы подготовить заранее к лекции, а не кодить в лайв-режиме)? Мне от этой лекции захотелось уснуть и после 20 минут попыток что-то настроить и показать, пропала вся нить повествования, если убрать это и оставить только удачную попытку, уверен эффект обучения будет лучше. + сэкономленное время ","creator":{"public_name":"Иван Дёгтев","id":714699,"is_tutor":false},"comments":[{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":190528,"body":"Приветствую, Иван! Спасибо, забрал ваш фидбек, создал тикет","topic_id":99151}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Многопоточность","entity_url":null,"active":true}},{"id":102660,"title":"Где-то на 17 минуте. То что выведено на экран озвучивается автором по другому. Толи это на экране перепутано, то ли автор объясняя немного заговаривается. Так как тут идет описание основ многопоточности, то хотелось бы какой-то определенности.","plain_title":"Где-то на 17 минуте. То что выведено на экран озвучивается автором по другому. Толи это на экране перепутано, то ли автор объясняя немного заговаривается. Так как тут идет описание основ многопоточности, то хотелось бы какой-то определенности. ","creator":{"public_name":"Александр","id":659898,"is_tutor":false},"comments":[{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":194912,"body":"Приветствую, Александр! Да, мы знаем про этот курс, с ним есть некоторые проблемы. В планах есть заменить его на наш стандартный текстовый, но по срокам вам пока не подскажу","topic_id":102660}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Многопоточность","entity_url":null,"active":true}},{"id":102987,"title":"Лекцию бы переснять или в текстовом виде расписать. Сложно понять тему.","plain_title":"Лекцию бы переснять или в текстовом виде расписать. Сложно понять тему. ","creator":{"public_name":"Ильшат Хабиров","id":766572,"is_tutor":false},"comments":[{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":195360,"body":"Приветствую, Ильшат! Да, мы знаем про этот курс. В планах есть переделать его на обычный текстовый","topic_id":102987}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Многопоточность","entity_url":null,"active":true}}],"lesson":{"exercise":{"id":4354,"slug":"java_advanced_multithreading_exercise","name":null,"state":"active","kind":"exercise","language":"java","locale":"ru","has_web_view":false,"has_test_view":false,"reviewable":true,"readme":"Многопоточность – это свойство платформы (например, операционной системы, виртуальной машины и т. д.) или приложения, состоящее в том, что процесс, порождённый в операционной системе, может состоять из нескольких потоков, выполняющихся параллельно. Мы только начинаем знакомиться с многопоточностью и это домашнее задание будет не сложным. В нём не будет Java-кода. Мы проследим, как происходит параллельное выполнение операций на примере работы в командной оболочке. Вам нужно будет повторить описанные действия в терминале и изучить полученные результаты.\n\nЕсть много таких задач, которые мы можем решить выполнять параллельно, например скачивание большого количества файлов, декодирование большого количества изображений. Конечно, все эти задачи можно решать и без использования распараллеливания. Но если мы обрабатываем каждый файл параллельно, мы можем получить большое преимущество с точки зрения скорости. В командной оболочке Bash есть несколько инструментов для распараллеливания, которые могут помочь нам в этом.\n\nСначала нам нужно создать скрипт, который мы будем выполнять параллельно с помощью *parallel*.\n\n## process.sh\n\nВ файл `process.sh` добавьте следующий код:\n\n```bash\necho \"started processing $*..\"\nsleep $((2+ RANDOM % 3));\necho finished processing \"$*\";\n```\n\nЭтот скрипт будет имитировать реальную обработку объёмного изображения. Его выполнение будет занимать от 2 до 5 секунд. В качестве аргумента программа будет принимать имя файла, который нужно обработать\n\n## Работа в терминале\n\n* Выполните этот скрипт в терминале, чтобы проверить, как он работает:\n\n ```bash\n ./process.sh 1.jpg\n ```\n\nВыполнение займет некоторое время. Программа не выполняет никаких полезных действий, только сигнализирует о начале и окончании своей работы. Вывод получится такой:\n\n ```bash\n started processing 1.jpg...\n finished processing 1.jpg\n ```\n\nБазовый способ выполнять операции параллельно в Bash – это использование оператора `&`. Попробуем выполнить обработку двух изображений параллельно.\n\n* Выполните в терминале следующий код и изучите результат:\n\n ```bash\n ./process.sh 1.jpg & ./process.sh 2.jpg & wait\n ```\n\n Обработка обоих файлов запустится примерно в одно и то же время и будет проходить параллельно. Поскольку время обработки случайное, вывод может получиться таким:\n\n ```bash\n started processing 2.jpg..\n started processing 1.jpg..\n finished processing 2.jpg\n finished processing 1.jpg\n ```\n\n Обратите внимание, что выполнение обработки двух изображений началось практически одновременно. Использование команды `wait` заставит Bash дождаться окончания всех операций.\n\nМы можем использовать этот подход для параллельной обработки нескольких изображений. Но если изображений много, например сотня, нам не нужно будет запускать обработку всех 100 изображений одновременно. Вместо этого лучше будет обрабатывать изображения партиями по несколько штук, чтобы эффективнее использовать ядра процессора. Наиболее продвинутым инструментом для параллельного запуска является утилита `Parallel`.\n\n* Используя пакетный менеджер своей ОС, установите утилиту GNU Parallel.\n\n* Скопируйте в терминал следующую команду:\n\n ```bash\n parallel --ungroup --jobs 3 ./process.sh ::: 1 2 3 4 5 6\n ```\n\n Разберем эту команду подробнее. Опция `–ungroup` позволяет нам проследить процесс работы во время выполнения. Опция `--jobs` задаёт максимальное количество параллельно запущенных работ. Далее мы указываем нашу утилиту, которая будет выполняться параллельно. Через тройное двоеточие `:::` указываем список аргументов, которые будут переданы в утилиту.\n\n* Выполните команду и изучите получившийся результат. Вывод может получиться примерно такой:\n\n ``` sh\n started processing 1...\n started processing 2...\n started processing 3...\n finished processing 2\n finished processing 3\n started processing 4...\n started processing 5...\n finished processing 1\n started processing 6...\n finished processing 4\n finished processing 5\n finished processing 6\n ```\n\n Так как мы указали максимальное количество задач в параллели 3, обработка первых трёх изображений началась практически одновременно. Обратите внимание, что утилита не дожидается окончания обработки всей партии из 3 изображений. Как только обработка второго и третьего закончилась, сразу запустилась обработка четвёртого и пятого, не дожидаясь окончания обработки первого. Это позволяет эффективно использовать ресурсы, так как мощности не простаивают в ожидании окончания обработки всей партии.\n\nЕсли максимальное количество одновременно запущенных работ не указывать, по умолчанию оно будет равно количеству ядер процессора.\n\n* Попробуйте запустить утилиту parallel без опции `--jobs` и проверьте, какое количество процессов у вас будет запущено параллельно:\n\n ```bash\n parallel --ungroup ./process.sh ::: 1 2 3 4 5 6 7 8 9 10\n ```\n\n Вывод может получиться такой:\n\n ```bash\n started processing 1..\n started processing 2..\n started processing 3..\n started processing 4..\n started processing 5..\n started processing 6..\n started processing 7..\n started processing 8..\n finished processing 3\n finished processing 5\n started processing 9..\n started processing 10..\n finished processing 1\n finished processing 4\n finished processing 2\n finished processing 6\n finished processing 7\n finished processing 8\n finished processing 9\n finished processing 10\n ```\n","prepared_readme":"Многопоточность – это свойство платформы (например, операционной системы, виртуальной машины и т. д.) или приложения, состоящее в том, что процесс, порождённый в операционной системе, может состоять из нескольких потоков, выполняющихся параллельно. Мы только начинаем знакомиться с многопоточностью и это домашнее задание будет не сложным. В нём не будет Java-кода. Мы проследим, как происходит параллельное выполнение операций на примере работы в командной оболочке. Вам нужно будет повторить описанные действия в терминале и изучить полученные результаты.\n\nЕсть много таких задач, которые мы можем решить выполнять параллельно, например скачивание большого количества файлов, декодирование большого количества изображений. Конечно, все эти задачи можно решать и без использования распараллеливания. Но если мы обрабатываем каждый файл параллельно, мы можем получить большое преимущество с точки зрения скорости. В командной оболочке Bash есть несколько инструментов для распараллеливания, которые могут помочь нам в этом.\n\nСначала нам нужно создать скрипт, который мы будем выполнять параллельно с помощью *parallel*.\n\n## process.sh\n\nВ файл `process.sh` добавьте следующий код:\n\n```bash\necho \"started processing $*..\"\nsleep $((2+ RANDOM % 3));\necho finished processing \"$*\";\n```\n\nЭтот скрипт будет имитировать реальную обработку объёмного изображения. Его выполнение будет занимать от 2 до 5 секунд. В качестве аргумента программа будет принимать имя файла, который нужно обработать\n\n## Работа в терминале\n\n* Выполните этот скрипт в терминале, чтобы проверить, как он работает:\n\n ```bash\n ./process.sh 1.jpg\n ```\n\nВыполнение займет некоторое время. Программа не выполняет никаких полезных действий, только сигнализирует о начале и окончании своей работы. Вывод получится такой:\n\n ```bash\n started processing 1.jpg...\n finished processing 1.jpg\n ```\n\nБазовый способ выполнять операции параллельно в Bash – это использование оператора `&`. Попробуем выполнить обработку двух изображений параллельно.\n\n* Выполните в терминале следующий код и изучите результат:\n\n ```bash\n ./process.sh 1.jpg & ./process.sh 2.jpg & wait\n ```\n\n Обработка обоих файлов запустится примерно в одно и то же время и будет проходить параллельно. Поскольку время обработки случайное, вывод может получиться таким:\n\n ```bash\n started processing 2.jpg..\n started processing 1.jpg..\n finished processing 2.jpg\n finished processing 1.jpg\n ```\n\n Обратите внимание, что выполнение обработки двух изображений началось практически одновременно. Использование команды `wait` заставит Bash дождаться окончания всех операций.\n\nМы можем использовать этот подход для параллельной обработки нескольких изображений. Но если изображений много, например сотня, нам не нужно будет запускать обработку всех 100 изображений одновременно. Вместо этого лучше будет обрабатывать изображения партиями по несколько штук, чтобы эффективнее использовать ядра процессора. Наиболее продвинутым инструментом для параллельного запуска является утилита `Parallel`.\n\n* Используя пакетный менеджер своей ОС, установите утилиту GNU Parallel.\n\n* Скопируйте в терминал следующую команду:\n\n ```bash\n parallel --ungroup --jobs 3 ./process.sh ::: 1 2 3 4 5 6\n ```\n\n Разберем эту команду подробнее. Опция `–ungroup` позволяет нам проследить процесс работы во время выполнения. Опция `--jobs` задаёт максимальное количество параллельно запущенных работ. Далее мы указываем нашу утилиту, которая будет выполняться параллельно. Через тройное двоеточие `:::` указываем список аргументов, которые будут переданы в утилиту.\n\n* Выполните команду и изучите получившийся результат. Вывод может получиться примерно такой:\n\n ``` sh\n started processing 1...\n started processing 2...\n started processing 3...\n finished processing 2\n finished processing 3\n started processing 4...\n started processing 5...\n finished processing 1\n started processing 6...\n finished processing 4\n finished processing 5\n finished processing 6\n ```\n\n Так как мы указали максимальное количество задач в параллели 3, обработка первых трёх изображений началась практически одновременно. Обратите внимание, что утилита не дожидается окончания обработки всей партии из 3 изображений. Как только обработка второго и третьего закончилась, сразу запустилась обработка четвёртого и пятого, не дожидаясь окончания обработки первого. Это позволяет эффективно использовать ресурсы, так как мощности не простаивают в ожидании окончания обработки всей партии.\n\nЕсли максимальное количество одновременно запущенных работ не указывать, по умолчанию оно будет равно количеству ядер процессора.\n\n* Попробуйте запустить утилиту parallel без опции `--jobs` и проверьте, какое количество процессов у вас будет запущено параллельно:\n\n ```bash\n parallel --ungroup ./process.sh ::: 1 2 3 4 5 6 7 8 9 10\n ```\n\n Вывод может получиться такой:\n\n ```bash\n started processing 1..\n started processing 2..\n started processing 3..\n started processing 4..\n started processing 5..\n started processing 6..\n started processing 7..\n started processing 8..\n finished processing 3\n finished processing 5\n started processing 9..\n started processing 10..\n finished processing 1\n finished processing 4\n finished processing 2\n finished processing 6\n finished processing 7\n finished processing 8\n finished processing 9\n finished processing 10\n ```\n","has_solution":true,"entity_name":"Многопоточность"},"units":[{"id":5206,"name":"theory","url":"/courses/java-advanced/lessons/multithreading/theory_unit"},{"id":13344,"name":"quiz","url":"/courses/java-advanced/lessons/multithreading/quiz_unit"},{"id":14637,"name":"exercise","url":"/courses/java-advanced/lessons/multithreading/exercise_unit"}],"links":[{"id":424868,"name":"Утилита GNU Parallel для параллельного выполнения","url":"https://www.gnu.org/software/parallel/parallel_tutorial.html"},{"id":424869,"name":"Установка утилиты GNU Parallel в Ubuntu","url":"https://onstartup.ru/utility/parallel/"},{"id":424870,"name":"Установка утилиты GNU Parallel в MacOS","url":"https://formulae.brew.sh/formula/parallel"}],"ordered_units":[{"id":5206,"name":"theory","url":"/courses/java-advanced/lessons/multithreading/theory_unit"},{"id":13344,"name":"quiz","url":"/courses/java-advanced/lessons/multithreading/quiz_unit"},{"id":14637,"name":"exercise","url":"/courses/java-advanced/lessons/multithreading/exercise_unit"}],"id":2356,"slug":"multithreading","state":"approved","name":"Многопоточность","course_order":110,"goal":"Выясняем, что такое многопоточность","self_study":null,"theory_video_provider":"vimeo","theory_video_uid":"667761696","theory":"## Многозадачность\n\nМногозадачность — это способность операционной системы одновременно выполнять несколько программ.\n\nОна позволяет пользователю работать с несколькими приложениями, например, слушать музыку, писать текст и просматривать интернет одновременно. Операционная система управляет ресурсами компьютера, чтобы каждая программа могла получать необходимое время и память для работы. Это делает использование компьютера более удобным и эффективным.\n\nБез многозадачности пользователь мог бы запускать только одно приложение за раз. Например, если мы слушаем музыку,то смогли бы одновременно просматривать новости в интернете — для этого пришлось бы закрывать одно приложение, чтобы открыть другое. Это сделало бы использование компьютера менее удобным и эффективным\n\nМногозадачность не является свойством языка программирования Java, а является функцией операционной системы. Язык Java может использовать многозадачность через потоки, которые создаются на основе системных потоков операционной системы для выполнения нескольких задач одновременно. Java предоставляет API для создания и управления этими потоками, но сама операционная система управляет их выполнением и ресурсами. Таким образом, многозадачность является фундаментальной функцией операционной системы, которая позволяет языкам программирования, таким как Java, создавать более эффективные и удобные приложения\n\n## Многопоточность\n\nМногопоточность — это возможность программы выполнять несколько задач одновременно, используя так называемые потоки. Поток — это отдельная часть программы, которая может работать параллельно с другими потоками.\n\n### Многопоточность и многозадачность\n\nМногозадачность и многопоточность - это два понятия, которые часто путают друг с другом, но они имеют разные значения, работают на разных уровнях. Многозадачность касается управления несколькими программами на уровне операционной системы. Например, вы открываете браузер и текстовый редактор, одновременно набираете текст и слушаете музыку. Многопоточность позволяет выполнять несколько задач внутри одной программы. Например, браузер загружает данные из интернета и одновременно отображает информацию на экране, не дожидаясь завершения загрузки.\n\nТаким образом основная разница между многозадачностью и многопоточностью заключается в том, что многозадачность относится к выполнению нескольких программ или процессов одновременно, а многопоточность относится к выполнению нескольких задач или потоков внутри одной программы или процесса.\n\nПо-настоящему параллельное выполнение задач возможно только в многоядерной системе, поскольку только в них присутствуют несколько системных конвейеров для исполнения команд. В одноядерной многозадачной системе поддерживается так называемое псевдопараллельное исполнение, при котором создается видимость параллельной работы нескольких процессов. В таких системах процессы выполняются последовательно, занимая малые кванты процессорного времени.\n\n## Возможности многопоточности\n\nМногопоточность - это мощный инструмент, который широко используется в приложениях с пользовательским интерфейсом. Основная идея многопоточности заключается в том, чтобы разделить задачи на несколько потоков, что позволяет выполнять несколько задач одновременно. Это особенно полезно в приложениях, где за работу интерфейса отвечает один поток, а какие-либо вычисления выполняются в других потоках.\n\nТаким образом, пользовательский интерфейс не подвисает, когда приложение занято другими вычислениями. Например, если вы открываете текстовый редактор и начинаете набирать текст, редактор может выполнять другие задачи, такие как проверка орфографии или автосохранение документа, в отдельных потоках. Это позволяет интерфейсу редактора оставаться отзывчивым и не подвисать.\n\nМногопоточность также полезна, когда алгоритмы можно разбить на независимые подзадачи, которые можно выполнять в разных потоках. Например, при фильтрации изображения разные потоки могут заниматься фильтрацией разных частей изображения. Это позволяет повысить производительность и ускорить выполнение задач.\n\nКроме того, многопоточность полезна, когда некоторые части приложения вынуждены ждать ответа от сервера, пользователя или устройства. В этом случае эти операции можно выделить в отдельный поток, чтобы в основном потоке можно было продолжать работу, пока другой поток ждёт ответа. Это позволяет приложению оставаться отзывчивым, даже если некоторые операции требуют времени для выполнения.\n\n## Процесс и поток\n\nПроцесс и поток — это два ключевых понятия в области операционных систем, которые относятся к выполнению программ\n\n**Процесс** — это экземпляр выполняемой программы. Он включает в себя не только код программы, но и все необходимые ресурсы для её выполнения, такие как память, открытые файлы и состояние выполнения, кроме процесорного времени. Каждый процесс имеет свою собственную область памяти, что обеспечивает изоляцию между процессами. Это значит, что один процесс не может напрямую обращаться к памяти другого процесса, что помогает предотвратить ошибки и конфликты.\n\n**Поток** — это наименьшая единица выполнения в рамках процесса. Каждый процесс может содержать один или несколько потоков. Потоки внутри одного процесса разделяют общую память и ресурсы, что позволяет им взаимодействовать друг с другом более эффективно. Это делает потоки легче и быстрее в создании и управлении по сравнению с процессами.\n\nРазница между процессом и потоком заключается в том, что процесс — это способ организовать все необходимые ресурсы для выполнения программы, а потоки — это единицы выполнения, которые используют процессорное время для выполнения конкретных задач. Таким образом, процессы организуют ресурсы, а потоки выполняют работу.\n\nПотоки легче создавать и управлять, так как они используют общие ресурсы процесса. Потоки могут легко обмениваться данными и взаимодействовать друг с другом, так как они работают в одной области памяти.\n\n### Состояние потоков\n\nПотоки в операционной системе могут находиться в различных состояниях в зависимости от того, что они делают в данный момент. Эти состояния помогают управлять выполнением потоков и оптимизировать использование ресурсов процессора. Вот основные состояния потока:\n\n- Выполняемый (Executing) - поток, который выполняется в текущий момент на процессоре.\n- Готовый (Runnable) - поток ждет получения кванта времени и готов выполнять назначенные ему инструкции. Планировщик выбирает следующий поток для выполнения только из готовых потоков.\n- Ожидающий (Waiting) - работа потока заблокирована в ожидании блокирующей операции.\n\n## Проблемы многопоточности\n\nМногопоточность может значительно повысить производительность и отзывчивость приложений, но она также может привести к различным проблемам, которые затрудняют разработку и отладку. Вот некоторые из основных проблем, с которыми могут столкнуться разработчики при работе с многопоточными системами\n\n### Состояние гонки\n\nСостояние гонки — это ошибка проектирования многопоточной системы или приложения, при которой результат работы системы зависит от порядка выполнения различных частей кода. Это происходит, когда несколько потоков одновременно пытаются изменить одну и ту же переменную или ресурс без должной синхронизации. В результате, если порядок выполнения потоков изменится, это может привести к непредсказуемым и ошибочным результатам, что делает систему нестабильной и трудной для отладки.\n\nЭто наш разделяемый ресурс\n\n```java\nclass Counter {\n\n private int counter = 0;\n\n public void increment() {\n counter++;\n }\n\n public int getCounter() {\n return counter;\n }\n}\n```\n\nДва потока пытаются изменить наш разделяемый ресурс без синхронизации. Например, поток 1 считывает текущее значение `counter`, а затем поток 2 также считывает это значение до того, как поток 1 успевает его обновить, оба потока могут записать одно и то же значение, что приводит к потере инкремента.\n\n```java\nclass Main {\n public static void main(String[] args) throws InterruptedException {\n Counter counter = new Counter();\n\n Thread thread1 = new Thread(() -> {\n for (int i = 0; i < 10000; i++) {\n counter.increment();\n }\n });\n\n Thread thread2 = new Thread(() -> {\n for (int i = 0; i < 10000; i++) {\n counter.increment();\n }\n });\n\n thread1.start();\n thread2.start();\n thread2.join();\n thread1.join();\n // Значение счетчика каждый запуск будет разным\n // Практически никогда оно не будет равно 20000\n System.out.println(counter.getCounter()); // 14836\n }\n}\n```\n\nВ результате, при каждом запуске программы значение счетчика, выводимое на экран, будет разным и, как правило, не будет равно ожидаемому значению 20000\n\n### Deadlock\n\nDeadlock (взаимная блокировка) — это ситуация, при которой несколько потоков находятся в состоянии ожидания ресурсов, занятых друг другом, и ни один из них не может продолжать выполнение. Например, поток A может удерживать ресурс 1 и ожидать ресурс 2, в то время как поток B удерживает ресурс 2 и ожидает ресурс 1. В результате оба потока застревают, и система не может продолжать работу, что приводит к потере производительности и необходимости ручного вмешательства для разрешения ситуации\n\n### Голодание потоков\n\nГолодание потоков — это ситуация, в которой поток не может получить доступ к общим ресурсам, потому что на эти ресурсы всегда претендуют другие потоки, которым отдается предпочтение. Это может произойти, если планировщик потоков неравномерно распределяет процессорное время или если некоторые потоки имеют более высокий приоритет. В результате, потоки с низким приоритетом могут никогда не получить возможность выполнить свою работу\n\n```java\nclass Main {\n public static void main(String[] args) throws InterruptedException {\n Counter counter = new Counter();\n\n Thread thread1 = new Thread(() -> {\n for (int i = 0; i < 10000; i++) {\n counter.increment();\n }\n });\n\n Thread thread2 = new Thread(() -> {\n for (int i = 0; i < 10000; i++) {\n counter.increment();\n }\n });\n\n thread1.start();\n thread2.start();\n thread2.join();\n thread1.join();\n // Значение счетчика каждый запуск будет разным\n // Практически никогда оно не будет равно 20000\n System.out.println(counter.getCounter()); // 14836\n }\n}\n```\n\nКласс потока\n\n```java\nclass Counter {\n\n private int counter = 0;\n\n public void increment() {\n counter++;\n }\n\n public int getCounter() {\n return counter;\n }\n}\n```\n"},"lessonMember":null,"courseMember":null,"course":{"start_lesson":{"exercise":null,"units":[{"id":7156,"name":"theory","url":"/courses/java-advanced/lessons/intro/theory_unit"}],"links":[],"ordered_units":[{"id":7156,"name":"theory","url":"/courses/java-advanced/lessons/intro/theory_unit"}],"id":3185,"slug":"intro","state":"approved","name":"Введение","course_order":100,"goal":"Знакомимся с целями и задачами курса","self_study":null,"theory_video_provider":null,"theory_video_uid":null,"theory":"В этом курсе мы рассмотрим продвинутые темы языка Java и важнейшие аспекты программирования в целом.\n\nОдной из центральных тем будет многопоточность. Мы обсудим, как создавать и управлять потоками, а также как синхронизировать их работу для достижения максимальной производительности и избежания проблем, связанных с конкурентным доступом к ресурсам.\n\nТакже мы уделим внимание асинхронности, которая позволяет выполнять задачи параллельно, не блокируя основной поток выполнения. Мы рассмотрим различные подходы к асинхронному программированию в Java, включая использование `CompletableFuture` и реактивного программирования. Это знание поможет вам создавать более отзывчивые и эффективные приложения.\n\nКроме того, мы изучим использование TestContainers — библиотеки, которая позволяет создавать и управлять контейнерами для тестирования. TestContainers предоставляет возможность запускать изолированные экземпляры баз данных, брокеров сообщений и других сервисов в контейнерах Docker прямо из ваших тестов. Это значительно упрощает процесс тестирования, так как вы сможете легко настраивать и очищать окружение для каждого теста, что обеспечивает высокую степень надежности и воспроизводимости\n"},"id":257,"slug":"java-advanced","challenges_count":0,"name":"Java: Продвинутое использование","allow_indexing":true,"state":"approved","course_state":"finished","pricing_type":"paid","description":"В этом курсе вы изучите продвинутые техники использования языка программирования Java. Вы узнаете о многопоточности и асинхронности, познакомитесь с Docker — одним из самых известных инструментов для автоматизации развертывания и управления приложениями. В итоге вы научитесь разрабатывать многопоточные приложения, поработаете с асинхронностью в Spring Boot. Так вы сможете упаковать свое приложение в контейнер и запустить его, а также же научитесь использовать контейнеры для тестирования приложения. Знания из этого курса помогут выйти на новый, продвинутый уровень владения языком Java.","kind":"additional","updated_at":"2026-01-20T11:50:41.941Z","language":"java","duration_cache":22920,"skills":["Работать с многопоточностью","Писать асинхронный код","Работать с docker"],"keywords":[],"lessons_count":8,"cover":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6ODIwNSwicHVyIjoiYmxvYl9pZCJ9fQ==--f3a08e2a31b9b2e09b1e397e67328ae419ecbb9d/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJwbmciLCJyZXNpemVfdG9fZmlsbCI6WzYwMCw0MDBdfSwicHVyIjoidmFyaWF0aW9uIn19--6067466c2912ca31a17eddee04b8cf2a38c6ad17/image.png"},"recommendedLandings":[{"stack":{"id":3,"slug":"java","title":"Java-разработчик","audience":"for_beginners","start_type":"weekly","pricing_model":"purchase","priority":"high","kind":"profession","state":"published","stack_state":"finished","order":30,"duration_in_months":10},"id":3,"slug":"java","title":"Java-разработчик","subtitle":"Изучите Java и фреймворк Spring Boot и REST API","subtitle_for_lists":"Изучите Java и фреймворк Spring Boot и REST API","locale":"ru","current":true,"duration_in_months_text":"10 месяцев","stack_slug":"java","price_text":"от 6 792 ₽","duration_text":"10 месяцев","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzczNSwicHVyIjoiYmxvYl9pZCJ9fQ==--883f3fd4e1b571538035b5680c8d4a9eb504b1f6/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Source%20code-amico.png"},{"stack":{"id":467,"slug":"middle-java","title":"Middle-java разработчик","audience":"for_programmers","start_type":"weekly","pricing_model":"purchase","priority":"high","kind":"profession","state":"published","stack_state":"not_finished","order":2002,"duration_in_months":6},"id":595,"slug":"middle-java","title":"Middle-java разработчик","subtitle":"Углубите знания Java, Spring и архитектуры серверных приложений","subtitle_for_lists":"Углубите знания Java, Spring и архитектуры серверных приложений","locale":"ru","current":true,"duration_in_months_text":"6 месяцев","stack_slug":"middle-java","price_text":"от 4 050 ₽","duration_text":"6 месяцев","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NTIxOSwicHVyIjoiYmxvYl9pZCJ9fQ==--e79a18f1e9f90eae650f1f4f04115cba51f4e650/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-amico.png"}],"lessonMemberUnit":null,"accessToLearnUnitExists":false,"accessToCourseExists":false},"url":"/courses/java-advanced/lessons/multithreading/theory_unit","version":"0b0c6d4ebbd40fd58630a0dd89cc25544ccdf24e","encryptHistory":false,"clearHistory":false}"><style data-mantine-styles="true">:root, :host{--mantine-font-family: Arial, sans-serif;--mantine-font-family-headings: Arial, sans-serif;--mantine-heading-font-weight: normal;--mantine-radius-default: 0rem;--mantine-primary-color-filled: var(--mantine-color-indigo-filled);--mantine-primary-color-filled-hover: var(--mantine-color-indigo-filled-hover);--mantine-primary-color-light: var(--mantine-color-indigo-light);--mantine-primary-color-light-hover: var(--mantine-color-indigo-light-hover);--mantine-primary-color-light-color: var(--mantine-color-indigo-light-color);--mantine-spacing-xxl: calc(4rem * var(--mantine-scale));--mantine-font-size-xs: 12px;--mantine-font-size-sm: 14px;--mantine-font-size-md: 16px;--mantine-font-size-lg: clamp(16.0000px, calc(15.2727px + 0.2273vw), 18.0000px);--mantine-font-size-xl: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-display-3: clamp(32.0000px, calc(26.1818px + 1.8182vw), 48.0000px);--mantine-font-size-display-2: clamp(36.0000px, calc(25.8182px + 3.1818vw), 64.0000px);--mantine-font-size-display-1: clamp(40.0000px, calc(25.4545px + 4.5455vw), 80.0000px);--mantine-font-size-h1: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-font-size-h2: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-font-size-h3: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-font-size-h4: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-font-size-h5: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-h6: 1rem;--mantine-primary-color-0: var(--mantine-color-indigo-0);--mantine-primary-color-1: var(--mantine-color-indigo-1);--mantine-primary-color-2: var(--mantine-color-indigo-2);--mantine-primary-color-3: var(--mantine-color-indigo-3);--mantine-primary-color-4: var(--mantine-color-indigo-4);--mantine-primary-color-5: var(--mantine-color-indigo-5);--mantine-primary-color-6: var(--mantine-color-indigo-6);--mantine-primary-color-7: var(--mantine-color-indigo-7);--mantine-primary-color-8: var(--mantine-color-indigo-8);--mantine-primary-color-9: var(--mantine-color-indigo-9);--mantine-color-red-0: #ffeaea;--mantine-color-red-1: #fed4d4;--mantine-color-red-2: #f4a7a8;--mantine-color-red-3: #ec7878;--mantine-color-red-4: #e55050;--mantine-color-red-5: #e03131;--mantine-color-red-6: #e02829;--mantine-color-red-7: #c71a1c;--mantine-color-red-8: #b21218;--mantine-color-red-9: #9c0411;--mantine-color-violet-0: #fce9ff;--mantine-color-violet-1: #f1cfff;--mantine-color-violet-2: #e09bff;--mantine-color-violet-3: #d16fff;--mantine-color-violet-4: #be37fe;--mantine-color-violet-5: #b51afe;--mantine-color-violet-6: #b009ff;--mantine-color-violet-7: #9b00e4;--mantine-color-violet-8: #8a00cc;--mantine-color-violet-9: #7800b3;--mantine-color-indigo-0: #edecff;--mantine-color-indigo-1: #d6d5fe;--mantine-color-indigo-2: #aaa9f4;--mantine-color-indigo-3: #7b79eb;--mantine-color-indigo-4: #5451e4;--mantine-color-indigo-5: #3b37e0;--mantine-color-indigo-6: #2d2adf;--mantine-color-indigo-7: #1f1ec7;--mantine-color-indigo-8: #1819b2;--mantine-color-indigo-9: #0c149e;--mantine-color-cyan-0: #dffdff;--mantine-color-cyan-1: #caf5ff;--mantine-color-cyan-2: #99e8ff;--mantine-color-cyan-3: #64daff;--mantine-color-cyan-4: #3ccffe;--mantine-color-cyan-5: #24c8fe;--mantine-color-cyan-6: #00c2ff;--mantine-color-cyan-7: #00ade4;--mantine-color-cyan-8: #009acd;--mantine-color-cyan-9: #0085b5;--mantine-color-green-0: #e9fdec;--mantine-color-green-1: #d7f6dc;--mantine-color-green-2: #b0eab9;--mantine-color-green-3: #86df94;--mantine-color-green-4: #62d574;--mantine-color-green-5: #4ccf5f;--mantine-color-green-6: #3fcc54;--mantine-color-green-7: #2fb344;--mantine-color-green-8: #25a03b;--mantine-color-green-9: #138a2e;--mantine-color-yellow-0: #fff7e2;--mantine-color-yellow-1: #ffeecd;--mantine-color-yellow-2: #ffdc9c;--mantine-color-yellow-3: #ffc966;--mantine-color-yellow-4: #feb93a;--mantine-color-yellow-5: #feae1e;--mantine-color-yellow-6: #ffa90f;--mantine-color-yellow-8: #ca8200;--mantine-color-yellow-9: #af7000;--mantine-h1-font-size: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-h1-font-weight: normal;--mantine-h2-font-size: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-h2-font-weight: normal;--mantine-h3-font-size: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-h3-font-weight: normal;--mantine-h4-font-size: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-h4-font-weight: normal;--mantine-h5-font-size: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-h5-font-weight: normal;--mantine-h6-font-size: 1rem;--mantine-h6-font-weight: normal;}
:root[data-mantine-color-scheme="dark"], :host([data-mantine-color-scheme="dark"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-dark-filled: var(--mantine-color-dark-5);--mantine-color-dark-filled-hover: var(--mantine-color-dark-6);--mantine-color-dark-light: rgba(105, 105, 105, 0.15);--mantine-color-dark-light-hover: rgba(105, 105, 105, 0.2);--mantine-color-dark-light-color: var(--mantine-color-dark-0);--mantine-color-dark-outline: var(--mantine-color-dark-1);--mantine-color-dark-outline-hover: rgba(184, 184, 184, 0.05);--mantine-color-gray-filled: var(--mantine-color-gray-5);--mantine-color-gray-filled-hover: var(--mantine-color-gray-6);--mantine-color-gray-light: rgba(222, 226, 230, 0.15);--mantine-color-gray-light-hover: rgba(222, 226, 230, 0.2);--mantine-color-gray-light-color: var(--mantine-color-gray-0);--mantine-color-gray-outline: var(--mantine-color-gray-1);--mantine-color-gray-outline-hover: rgba(241, 243, 245, 0.05);--mantine-color-red-filled: var(--mantine-color-red-5);--mantine-color-red-filled-hover: var(--mantine-color-red-6);--mantine-color-red-light: rgba(236, 120, 120, 0.15);--mantine-color-red-light-hover: rgba(236, 120, 120, 0.2);--mantine-color-red-light-color: var(--mantine-color-red-0);--mantine-color-red-outline: var(--mantine-color-red-1);--mantine-color-red-outline-hover: rgba(254, 212, 212, 0.05);--mantine-color-pink-filled: var(--mantine-color-pink-5);--mantine-color-pink-filled-hover: var(--mantine-color-pink-6);--mantine-color-pink-light: rgba(250, 162, 193, 0.15);--mantine-color-pink-light-hover: rgba(250, 162, 193, 0.2);--mantine-color-pink-light-color: var(--mantine-color-pink-0);--mantine-color-pink-outline: var(--mantine-color-pink-1);--mantine-color-pink-outline-hover: rgba(255, 222, 235, 0.05);--mantine-color-grape-filled: var(--mantine-color-grape-5);--mantine-color-grape-filled-hover: var(--mantine-color-grape-6);--mantine-color-grape-light: rgba(229, 153, 247, 0.15);--mantine-color-grape-light-hover: rgba(229, 153, 247, 0.2);--mantine-color-grape-light-color: var(--mantine-color-grape-0);--mantine-color-grape-outline: var(--mantine-color-grape-1);--mantine-color-grape-outline-hover: rgba(243, 217, 250, 0.05);--mantine-color-violet-filled: var(--mantine-color-violet-5);--mantine-color-violet-filled-hover: var(--mantine-color-violet-6);--mantine-color-violet-light: rgba(209, 111, 255, 0.15);--mantine-color-violet-light-hover: rgba(209, 111, 255, 0.2);--mantine-color-violet-light-color: var(--mantine-color-violet-0);--mantine-color-violet-outline: var(--mantine-color-violet-1);--mantine-color-violet-outline-hover: rgba(241, 207, 255, 0.05);--mantine-color-indigo-filled: var(--mantine-color-indigo-5);--mantine-color-indigo-filled-hover: var(--mantine-color-indigo-6);--mantine-color-indigo-light: rgba(123, 121, 235, 0.15);--mantine-color-indigo-light-hover: rgba(123, 121, 235, 0.2);--mantine-color-indigo-light-color: var(--mantine-color-indigo-0);--mantine-color-indigo-outline: var(--mantine-color-indigo-1);--mantine-color-indigo-outline-hover: rgba(214, 213, 254, 0.05);--mantine-color-blue-filled: var(--mantine-color-blue-5);--mantine-color-blue-filled-hover: var(--mantine-color-blue-6);--mantine-color-blue-light: rgba(116, 192, 252, 0.15);--mantine-color-blue-light-hover: rgba(116, 192, 252, 0.2);--mantine-color-blue-light-color: var(--mantine-color-blue-0);--mantine-color-blue-outline: var(--mantine-color-blue-1);--mantine-color-blue-outline-hover: rgba(208, 235, 255, 0.05);--mantine-color-cyan-filled: var(--mantine-color-cyan-5);--mantine-color-cyan-filled-hover: var(--mantine-color-cyan-6);--mantine-color-cyan-light: rgba(100, 218, 255, 0.15);--mantine-color-cyan-light-hover: rgba(100, 218, 255, 0.2);--mantine-color-cyan-light-color: var(--mantine-color-cyan-0);--mantine-color-cyan-outline: var(--mantine-color-cyan-1);--mantine-color-cyan-outline-hover: rgba(202, 245, 255, 0.05);--mantine-color-teal-filled: var(--mantine-color-teal-5);--mantine-color-teal-filled-hover: var(--mantine-color-teal-6);--mantine-color-teal-light: rgba(99, 230, 190, 0.15);--mantine-color-teal-light-hover: rgba(99, 230, 190, 0.2);--mantine-color-teal-light-color: var(--mantine-color-teal-0);--mantine-color-teal-outline: var(--mantine-color-teal-1);--mantine-color-teal-outline-hover: rgba(195, 250, 232, 0.05);--mantine-color-green-filled: var(--mantine-color-green-5);--mantine-color-green-filled-hover: var(--mantine-color-green-6);--mantine-color-green-light: rgba(134, 223, 148, 0.15);--mantine-color-green-light-hover: rgba(134, 223, 148, 0.2);--mantine-color-green-light-color: var(--mantine-color-green-0);--mantine-color-green-outline: var(--mantine-color-green-1);--mantine-color-green-outline-hover: rgba(215, 246, 220, 0.05);--mantine-color-lime-filled: var(--mantine-color-lime-5);--mantine-color-lime-filled-hover: var(--mantine-color-lime-6);--mantine-color-lime-light: rgba(192, 235, 117, 0.15);--mantine-color-lime-light-hover: rgba(192, 235, 117, 0.2);--mantine-color-lime-light-color: var(--mantine-color-lime-0);--mantine-color-lime-outline: var(--mantine-color-lime-1);--mantine-color-lime-outline-hover: rgba(233, 250, 200, 0.05);--mantine-color-yellow-filled: var(--mantine-color-yellow-5);--mantine-color-yellow-filled-hover: var(--mantine-color-yellow-6);--mantine-color-yellow-light: rgba(255, 201, 102, 0.15);--mantine-color-yellow-light-hover: rgba(255, 201, 102, 0.2);--mantine-color-yellow-light-color: var(--mantine-color-yellow-0);--mantine-color-yellow-outline: var(--mantine-color-yellow-1);--mantine-color-yellow-outline-hover: rgba(255, 238, 205, 0.05);--mantine-color-orange-filled: var(--mantine-color-orange-5);--mantine-color-orange-filled-hover: var(--mantine-color-orange-6);--mantine-color-orange-light: rgba(255, 192, 120, 0.15);--mantine-color-orange-light-hover: rgba(255, 192, 120, 0.2);--mantine-color-orange-light-color: var(--mantine-color-orange-0);--mantine-color-orange-outline: var(--mantine-color-orange-1);--mantine-color-orange-outline-hover: rgba(255, 232, 204, 0.05);--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-9) 0%, var(--mantine-color-cyan-7) 100%);--app-color-surface: #2e2e2e;}
:root[data-mantine-color-scheme="light"], :host([data-mantine-color-scheme="light"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-red-light: rgba(224, 40, 41, 0.1);--mantine-color-red-light-hover: rgba(224, 40, 41, 0.12);--mantine-color-red-outline-hover: rgba(224, 40, 41, 0.05);--mantine-color-violet-light: rgba(176, 9, 255, 0.1);--mantine-color-violet-light-hover: rgba(176, 9, 255, 0.12);--mantine-color-violet-outline-hover: rgba(176, 9, 255, 0.05);--mantine-color-indigo-light: rgba(45, 42, 223, 0.1);--mantine-color-indigo-light-hover: rgba(45, 42, 223, 0.12);--mantine-color-indigo-outline-hover: rgba(45, 42, 223, 0.05);--mantine-color-cyan-light: rgba(0, 194, 255, 0.1);--mantine-color-cyan-light-hover: rgba(0, 194, 255, 0.12);--mantine-color-cyan-outline-hover: rgba(0, 194, 255, 0.05);--mantine-color-green-light: rgba(63, 204, 84, 0.1);--mantine-color-green-light-hover: rgba(63, 204, 84, 0.12);--mantine-color-green-outline-hover: rgba(63, 204, 84, 0.05);--mantine-color-yellow-light: rgba(255, 169, 15, 0.1);--mantine-color-yellow-light-hover: rgba(255, 169, 15, 0.12);--mantine-color-yellow-outline-hover: rgba(255, 169, 15, 0.05);--app-color-surface: #f1f3f5;--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-5) 100%);}</style><style data-mantine-styles="classes">@media (max-width: 35.99375em) {.mantine-visible-from-xs {display: none !important;}}@media (min-width: 36em) {.mantine-hidden-from-xs {display: none !important;}}@media (max-width: 47.99375em) {.mantine-visible-from-sm {display: none !important;}}@media (min-width: 48em) {.mantine-hidden-from-sm {display: none !important;}}@media (max-width: 61.99375em) {.mantine-visible-from-md {display: none !important;}}@media (min-width: 62em) {.mantine-hidden-from-md {display: none !important;}}@media (max-width: 74.99375em) {.mantine-visible-from-lg {display: none !important;}}@media (min-width: 75em) {.mantine-hidden-from-lg {display: none !important;}}@media (max-width: 87.99375em) {.mantine-visible-from-xl {display: none !important;}}@media (min-width: 88em) {.mantine-hidden-from-xl {display: none !important;}}</style><div style="position:absolute;top:0rem" class=""></div><div style="max-width:var(--container-size-xl);height:100%;min-height:0rem" class=""><style data-mantine-styles="inline">.__m__-_R_5ub_{--grid-gutter:0rem;}</style><div style="height:100%;min-height:0rem" class="m_410352e9 mantine-Grid-root __m__-_R_5ub_"><div class="m_dee7bd2f mantine-Grid-inner" style="height:100%"><style data-mantine-styles="inline">.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:91.66666666666667%;--col-max-width:91.66666666666667%;}@media(min-width: 48em){.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:83.33333333333334%;--col-max-width:83.33333333333334%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem;display:flex" class="m_96bdd299 mantine-Grid-col __m__-_R_rdub_"><style data-mantine-styles="inline">.__m__-_R_6qrdub_{margin-top:0rem;padding-inline:var(--mantine-spacing-xs);width:100%;}@media(min-width: 48em){.__m__-_R_6qrdub_{margin-top:var(--mantine-spacing-xl);width:80%;}}@media(min-width: 62em){.__m__-_R_6qrdub_{padding-inline:var(--mantine-spacing-xl);}}</style><div style="margin-inline:auto;max-width:var(--mantine-breakpoint-xl)" class="__m__-_R_6qrdub_"><div style="color:var(--mantine-color-dimmed)" class="m_4451eb3a mantine-Center-root" data-inline="true"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:calc(0.125rem * var(--mantine-scale));color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-lock "><path d="M5 13a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-6"></path><path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M8 11v-4a4 4 0 1 1 8 0v4"></path></svg></div><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Java: Продвинутое использование</p></div><h1 style="--title-fw:var(--mantine-h1-font-weight);--title-lh:var(--mantine-h1-line-height);--title-fz:var(--mantine-h1-font-size);margin-bottom:var(--mantine-spacing-xl)" class="m_8a5d1357 mantine-Title-root" data-order="1">Теория: Многопоточность</h1><script type="application/ld+json">{"@context":"https://schema.org","@type":"LearningResource","name":"Многопоточность","inLanguage":"ru","isPartOf":{"@type":"LearningResource","name":"Java: Продвинутое использование"},"isAccessibleForFree":"False","hasPart":{"@type":"WebPageElement","isAccessibleForFree":"False","cssSelector":".paywalled"}}</script><div class=""><div style="--alert-color:var(--mantine-color-indigo-light-color);margin-bottom:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-lg)" class="m_66836ed3 mantine-Alert-root" id="mantine-_R_remqrdub_" role="alert" aria-describedby="mantine-_R_remqrdub_-body" aria-labelledby="mantine-_R_remqrdub_-title"><div class="m_a5d60502 mantine-Alert-wrapper"><div class="m_667f2a6a mantine-Alert-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-rocket "><path d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3 -5a9 9 0 0 0 6 -8a3 3 0 0 0 -3 -3a9 9 0 0 0 -8 6a6 6 0 0 0 -5 3"></path><path d="M7 14a6 6 0 0 0 -3 6a6 6 0 0 0 6 -3"></path><path d="M14 9a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path></svg></div><div class="m_667c2793 mantine-Alert-body"><div class="m_6a03f287 mantine-Alert-title"><span id="mantine-_R_remqrdub_-title" class="m_698f4f23 mantine-Alert-label">Полный доступ к материалам</span></div><div id="mantine-_R_remqrdub_-body" class="m_7fa78076 mantine-Alert-message"><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Зарегистрируйтесь и получите доступ к этому и десяткам других курсов</p><a style="--button-height:var(--button-height-xs);--button-padding-x:var(--button-padding-x-xs);--button-fz:var(--mantine-font-size-xs);--button-bg:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-hover:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-color:var(--mantine-color-white);--button-bd:none" class="mantine-focus-auto mantine-active m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root" data-variant="gradient" data-size="xs" href="/u/new"><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">Зарегистрироваться</span></span></a></div></div></div></div></div><div class="paywalled m_d08caa0 mantine-Typography-root"><h2 id="heading-2-1">Многозадачность</h2>
<p>Многозадачность — это способность операционной системы одновременно выполнять несколько программ.</p>
<p>Она позволяет пользователю работать с несколькими приложениями, например, слушать музыку, писать текст и просматривать интернет одновременно. Операционная система управляет ресурсами компьютера, чтобы каждая программа могла получать необходимое время и память для работы. Это делает использование компьютера более удобным и эффективным.</p>
<p>Без многозадачности пользователь мог бы запускать только одно приложение за раз. Например, если мы слушаем музыку,то смогли бы одновременно просматривать новости в интернете — для этого пришлось бы закрывать одно приложение, чтобы открыть другое. Это сделало бы использование компьютера менее удобным и эффективным</p>
<p>Многозадачность не является свойством языка программирования Java, а является функцией операционной системы. Язык Java может использовать многозадачность через потоки, которые создаются на основе системных потоков операционной системы для выполнения нескольких задач одновременно. Java предоставляет API для создания и управления этими потоками, но сама операционная система управляет их выполнением и ресурсами. Таким образом, многозадачность является фундаментальной функцией операционной системы, которая позволяет языкам программирования, таким как Java, создавать более эффективные и удобные приложения</p>
<h2 id="heading-2-2">Многопоточность</h2>
<p>Многопоточность — это возможность программы выполнять несколько задач одновременно, используя так называемые потоки. Поток — это отдельная часть программы, которая может работать параллельно с другими потоками.</p>
<h3 id="heading-3-3">Многопоточность и многозадачность</h3>
<p>Многозадачность и многопоточность - это два понятия, которые часто путают друг с другом, но они имеют разные значения, работают на разных уровнях. Многозадачность касается управления несколькими программами на уровне операционной системы. Например, вы открываете браузер и текстовый редактор, одновременно набираете текст и слушаете музыку. Многопоточность позволяет выполнять несколько задач внутри одной программы. Например, браузер загружает данные из интернета и одновременно отображает информацию на экране, не дожидаясь завершения загрузки.</p>
<p>Таким образом основная разница между многозадачностью и многопоточностью заключается в том, что многозадачность относится к выполнению нескольких программ или процессов одновременно, а многопоточность относится к выполнению нескольких задач или потоков внутри одной программы или процесса.</p>
<p>По-настоящему параллельное выполнение задач возможно только в многоядерной системе, поскольку только в них присутствуют несколько системных конвейеров для исполнения команд. В одноядерной многозадачной системе поддерживается так называемое псевдопараллельное исполнение, при котором создается видимость параллельной работы нескольких процессов. В таких системах процессы выполняются последовательно, занимая малые кванты процессорного времени.</p>
<h2 id="heading-2-4">Возможности многопоточности</h2>
<p>Многопоточность - это мощный инструмент, который широко используется в приложениях с пользовательским интерфейсом. Основная идея многопоточности заключается в том, чтобы разделить задачи на несколько потоков, что позволяет выполнять несколько задач одновременно. Это особенно полезно в приложениях, где за работу интерфейса отвечает один поток, а какие-либо вычисления выполняются в других потоках.</p>
<p>Таким образом, пользовательский интерфейс не подвисает, когда приложение занято другими вычислениями. Например, если вы открываете текстовый редактор и начинаете набирать текст, редактор может выполнять другие задачи, такие как проверка орфографии или автосохранение документа, в отдельных потоках. Это позволяет интерфейсу редактора оставаться отзывчивым и не подвисать.</p>
<p>Многопоточность также полезна, когда алгоритмы можно разбить на независимые подзадачи, которые можно выполнять в разных потоках. Например, при фильтрации изображения разные потоки могут заниматься фильтрацией разных частей изображения. Это позволяет повысить производительность и ускорить выполнение задач.</p>
<p>Кроме того, многопоточность полезна, когда некоторые части приложения вынуждены ждать ответа от сервера, пользователя или устройства. В этом случае эти операции можно выделить в отдельный поток, чтобы в основном потоке можно было продолжать работу, пока другой поток ждёт ответа. Это позволяет приложению оставаться отзывчивым, даже если некоторые операции требуют времени для выполнения.</p>
<h2 id="heading-2-5">Процесс и поток</h2>
<p>Процесс и поток — это два ключевых понятия в области операционных систем, которые относятся к выполнению программ</p>
<p><strong>Процесс</strong> — это экземпляр выполняемой программы. Он включает в себя не только код программы, но и все необходимые ресурсы для её выполнения, такие как память, открытые файлы и состояние выполнения, кроме процесорного времени. Каждый процесс имеет свою собственную область памяти, что обеспечивает изоляцию между процессами. Это значит, что один процесс не может напрямую обращаться к памяти другого процесса, что помогает предотвратить ошибки и конфликты.</p>
<p><strong>Поток</strong> — это наименьшая единица выполнения в рамках процесса. Каждый процесс может содержать один или несколько потоков. Потоки внутри одного процесса разделяют общую память и ресурсы, что позволяет им взаимодействовать друг с другом более эффективно. Это делает потоки легче и быстрее в создании и управлении по сравнению с процессами.</p>
<p>Разница между процессом и потоком заключается в том, что процесс — это способ организовать все необходимые ресурсы для выполнения программы, а потоки — это единицы выполнения, которые используют процессорное время для выполнения конкретных задач. Таким образом, процессы организуют ресурсы, а потоки выполняют работу.</p>
<p>Потоки легче создавать и управлять, так как они используют общие ресурсы процесса. Потоки могут легко обмениваться данными и взаимодействовать друг с другом, так как они работают в одной области памяти.</p>
<h3 id="heading-3-6">Состояние потоков</h3>
<p>Потоки в операционной системе могут находиться в различных состояниях в зависимости от того, что они делают в данный момент. Эти состояния помогают управлять выполнением потоков и оптимизировать использование ресурсов процессора. Вот основные состояния потока:</p>
<ul>
<li>Выполняемый (Executing) - поток, который выполняется в текущий момент на процессоре.</li>
<li>Готовый (Runnable) - поток ждет получения кванта времени и готов выполнять назначенные ему инструкции. Планировщик выбирает следующий поток для выполнения только из готовых потоков.</li>
<li>Ожидающий (Waiting) - работа потока заблокирована в ожидании блокирующей операции.</li>
</ul>
<h2 id="heading-2-7">Проблемы многопоточности</h2>
<p>Многопоточность может значительно повысить производительность и отзывчивость приложений, но она также может привести к различным проблемам, которые затрудняют разработку и отладку. Вот некоторые из основных проблем, с которыми могут столкнуться разработчики при работе с многопоточными системами</p>
<h3 id="heading-3-8">Состояние гонки</h3>
<p>Состояние гонки — это ошибка проектирования многопоточной системы или приложения, при которой результат работы системы зависит от порядка выполнения различных частей кода. Это происходит, когда несколько потоков одновременно пытаются изменить одну и ту же переменную или ресурс без должной синхронизации. В результате, если порядок выполнения потоков изменится, это может привести к непредсказуемым и ошибочным результатам, что делает систему нестабильной и трудной для отладки.</p>
<p>Это наш разделяемый ресурс</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">class Counter {
private int counter = 0;
public void increment() {
counter++;
}
public int getCounter() {
return counter;
}
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Два потока пытаются изменить наш разделяемый ресурс без синхронизации. Например, поток 1 считывает текущее значение <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">counter</code>, а затем поток 2 также считывает это значение до того, как поток 1 успевает его обновить, оба потока могут записать одно и то же значение, что приводит к потере инкремента.</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
thread2.join();
thread1.join();
// Значение счетчика каждый запуск будет разным
// Практически никогда оно не будет равно 20000
System.out.println(counter.getCounter()); // 14836
}
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>В результате, при каждом запуске программы значение счетчика, выводимое на экран, будет разным и, как правило, не будет равно ожидаемому значению 20000</p>
<h3 id="heading-3-9">Deadlock</h3>
<p>Deadlock (взаимная блокировка) — это ситуация, при которой несколько потоков находятся в состоянии ожидания ресурсов, занятых друг другом, и ни один из них не может продолжать выполнение. Например, поток A может удерживать ресурс 1 и ожидать ресурс 2, в то время как поток B удерживает ресурс 2 и ожидает ресурс 1. В результате оба потока застревают, и система не может продолжать работу, что приводит к потере производительности и необходимости ручного вмешательства для разрешения ситуации</p>
<h3 id="heading-3-10">Голодание потоков</h3>
<p>Голодание потоков — это ситуация, в которой поток не может получить доступ к общим ресурсам, потому что на эти ресурсы всегда претендуют другие потоки, которым отдается предпочтение. Это может произойти, если планировщик потоков неравномерно распределяет процессорное время или если некоторые потоки имеют более высокий приоритет. В результате, потоки с низким приоритетом могут никогда не получить возможность выполнить свою работу</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
thread2.join();
thread1.join();
// Значение счетчика каждый запуск будет разным
// Практически никогда оно не будет равно 20000
System.out.println(counter.getCounter()); // 14836
}
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Класс потока</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">class Counter {
private int counter = 0;
public void increment() {
counter++;
}
public int getCounter() {
return counter;
}
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div></div><div style="margin-block:var(--mantine-spacing-xl)" class=""><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md)" class="m_8a5d1357 mantine-Title-root" data-order="2">Рекомендуемые программы</h2><style data-mantine-styles="inline">.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xs);--carousel-slide-size:70%;}@media(min-width: 36em){.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xl);--carousel-slide-size:50%;}}</style><div style="--carousel-control-size:calc(2.5rem * var(--mantine-scale));--carousel-controls-offset:var(--mantine-spacing-sm);margin-bottom:var(--mantine-spacing-lg);padding-block:var(--mantine-spacing-sm);background:var(--app-color-surface)" class="m_17884d0f mantine-Carousel-root responsiveClassName" data-orientation="horizontal" data-include-gap-in-size="true"><div class="m_39bc3463 mantine-Carousel-controls" data-orientation="horizontal"><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="previous" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="next" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div><div class="m_a2dae653 mantine-Carousel-viewport" data-type="media"><div class="m_fcd81474 mantine-Carousel-container __m__-_R_2mremqrdub_" data-orientation="horizontal"><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/java?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">10 месяцев</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">С нуля</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Java-разработчик</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Изучите Java и фреймворк Spring Boot и REST API</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzczNSwicHVyIjoiYmxvYl9pZCJ9fQ==--883f3fd4e1b571538035b5680c8d4a9eb504b1f6/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Source%20code-amico.png" alt="Java-разработчик" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 6 792 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/middle-java?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">6 месяцев</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Для продвинутых</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Middle-java разработчик</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Углубите знания Java, Spring и архитектуры серверных приложений</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NTIxOSwicHVyIjoiYmxvYl9pZCJ9fQ==--e79a18f1e9f90eae650f1f4f04115cba51f4e650/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-amico.png" alt="Middle-java разработчик" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 4 050 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md);font-size:var(--mantine-font-size-h3)" class="m_8a5d1357 mantine-Title-root" data-order="2" data-responsive="true">Каталог</h2><p style="margin-bottom:auto" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Полный список доступных курсов по разным направлениям</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="/vite/assets/development-BVihs_d5.png" alt="Orientation"/></div></div></div></a></div></div></div></div></div></div></div></div></div><style data-mantine-styles="inline">.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:8.333333333333334%;--col-max-width:8.333333333333334%;}@media(min-width: 48em){.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:16.666666666666668%;--col-max-width:16.666666666666668%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem" class="m_96bdd299 mantine-Grid-col __m__-_R_1bdub_"><div style="margin-inline:var(--mantine-spacing-xs)" class="mantine-visible-from-sm"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-lg);text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/java-advanced/lessons/multithreading/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label"><span style="margin-inline-end:var(--mantine-spacing-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Дальше</span>→</span></span></a><a style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Навигация по теме</span><span class="m_57492dcc mantine-NavLink-description">Теория</span></div><span class="m_690090b5 mantine-NavLink-section" data-position="right"></span></a><div style="margin-block:var(--mantine-spacing-lg)" class="m_3eebeb36 mantine-Divider-root" data-orientation="horizontal" role="separator"></div><div style="margin-block:var(--mantine-spacing-lg)" class=""><div style="justify-content:space-between;margin-bottom:calc(0.1875rem * var(--mantine-scale));color:var(--mantine-color-dimmed);font-size:var(--mantine-font-size-xs)" class="m_8bffd616 mantine-Flex-root __m__-_R_qimrbdub_"><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Завершено</p><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">0 / 8</p></div><div style="--progress-size:var(--progress-size-sm)" class="m_db6d6462 mantine-Progress-root" data-size="sm"><div style="--progress-section-size:0%;--progress-section-color:var(--mantine-color-gray-filled)" class="m_2242eb65 mantine-Progress-section" role="progressbar" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" aria-valuetext="0%"></div></div></div><button style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root" type="button"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Обсуждения (архив)</span><span class="m_57492dcc mantine-NavLink-description"></span></div></button><div style="--toc-bg:var(--mantine-color-blue-light);--toc-color:var(--mantine-color-blue-light-color);--toc-size:var(--mantine-font-size-sm);--toc-radius:var(--mantine-radius-sm);margin-top:var(--mantine-spacing-xl)" class="m_bcaa9990 mantine-TableOfContents-root" data-variant="light" data-size="sm"></div></div><div class="mantine-hidden-from-sm"><div style="--stack-gap:0rem;--stack-align:stretch;--stack-justify:flex-start" class="m_6d731127 mantine-Stack-root"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-xs);padding:0rem;text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/java-advanced/lessons/multithreading/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">→</span></span></a><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" data-disabled="true" type="button" disabled=""><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></span></button><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto mantine-active m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" type="button"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></span></button></div></div></div></div></div></div></div>
</main>
<footer class="bg-dark fw-light text-light px-3 py-5">
<div class="row small">
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 mb-3">Хекслет</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/about">О нас</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/testimonials">Отзывы</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://b2b.hexlet.io" role="button">Корпоративное обучение</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/blog">Блог</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/qna">Вопросы и ответы</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/glossary">Глоссарий</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://help.hexlet.io" data-target="_blank" role="button">Справка</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" target="_blank" rel="noopener noreferrer" href="/map">Карта сайта</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 fw-normal mb-3">Направления</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_devops">DevOps
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_data_analytics">Аналитика
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_backend_development">Бэкенд
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_programming">Программирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_testing">Тестирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_front_end_dev">Фронтенд
</a></li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Профессии</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/go">Go-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/java">Java-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python">Python-разработчик </a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/data-analytics">Аналитик данных</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/qa-engineer">Инженер по ручному тестированию</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php">РНР-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/frontend">Фронтенд-разработчик</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Навыки</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python-django-developer">Django</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/docker">Docker</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php-laravel-developer">Laravel</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/postman">Postman</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-react-developer">React</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-rest-api">REST API в Node.js</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/spring-boot">Spring Boot</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/typescript">Typescript</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="col-12 col-sm-4 col-md-2">
<div class="fs-4">
<ul class="list-unstyled d-flex">
<li class="me-3">
<a aria-label="Telegram" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://t.me/hexlet_ru"><span class="bi bi-telegram"></span>
</a></li>
<li>
<a aria-label="Youtube" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.youtube.com/user/HexletUniversity"><span class="bi bi-youtube"></span>
</a></li>
</ul>
</div>
<div class="mb-2 d-flex flex-column">
<a class="link-light text-decoration-none" rel="nofollow" href="mailto:support@hexlet.io">support@hexlet.io</a>
<a class="link-light text-decoration-none py-2" target="_blank" href="https://t.me/hexlet_help_bot">t.me/hexlet_help_bot</a>
</div>
<ul class="list-unstyled d-flex">
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://hexlet.io/locale/switch?new_locale=en" data-target="_self" role="button"><span class="my-auto">EN</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 opacity-100 external-link" rel="nofollow" data-href="https://ru.hexlet.io/locale/switch?new_locale=ru" data-target="_self" role="button"><span class="my-auto">RU</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://kz.hexlet.io/locale/switch?new_locale=kz" data-target="_self" role="button"><span class="my-auto">KZ</span>
</span></li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled fs-4">
<li class="mb-3">
<a class="link-light text-decoration-none" href="tel:8%20800%20100%2022%2047">8 800 100 22 47</a>
<span class="d-block opacity-50 small">бесплатно по РФ</span>
</li>
<li>
<a class="link-light text-decoration-none" href="tel:%2B7%20495%20085%2021%2062">+7 495 085 21 62</a>
<span class="d-block opacity-50 small">бесплатно по Москве</span>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<div class="small mb-3">Образовательные услуги оказываются на основании Л035-01298-77/01989008 от 14.03.2025</div>
<ul class="list-unstyled small">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/legal">Правовая информация</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/offer">Оферта</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/license">Лицензия</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/contacts">Контакты</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-12 col-md-4 small">
<div class="mb-2">
<div>ООО «<a href="/" class="text-decoration-none link-light">Хекслет Рус</a>»</div>
<div>108813 г. Москва, вн.тер.г. поселение Московский,</div>
<div>г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3</div>
<div>ОГРН 1217300010476</div>
<div>ИНН 7325174845</div>
</div>
<hr>
<div>АНО ДПО «<a href="/" class="text-decoration-none link-light">Учебный центр «Хекслет</a>»</div>
<div>119331 г. Москва, вн. тер. г. муниципальный округ</div>
<div>Ломоносовский, пр-кт Вернадского, д. 29</div>
<div>ОГРН 1247700712390</div>
<div>ИНН 7736364948</div>
</div>
</div>
</footer>
<div id="root-assistant-offcanvas"></div>
<script src="/vite/assets/assistant-CdBlNCiQ.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-nkZBEvfU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/MarkdownBlock-DbyKWoR_.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/shiki-V011pkdv.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-XR8Qr8kR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dist-GCHh59xr.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useIsomorphicEffect-HJ6VK0D3.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-KSp6QbZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/classnames-l6ipYlLR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/debounce-jMQ_Cf4f.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v67327c56f0bb4ef8b305cae61679db8f1769101564043" integrity="sha512-rdcWY47ByXd76cbCFzznIcEaCN71jqkWBBqlwhF1SY7KubdLKZiEGeP7AyieKZlGP9hbY/MhGrwXzJC/HulNyg==" data-cf-beacon='{"version":"2024.11.0","token":"d11015b65d11429ea6b4a2ef37dd7e0b","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>