[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-java-11-25-structured-concurrency-chto-eto-i-zachem":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":16,"progress":17,"seo":18},410,"structured-concurrency-chto-eto-i-zachem",11,"java-11-25","Java 11–25","🆕","Structured Concurrency — что это и зачем?","Structured Concurrency — API для управления группами связанных задач как единым целым. Гарантирует, что подзадачи завершатся (или будут отменены) до завершения родительской задачи, предотвращая утечки потоков.\n\n> **Аналогия из жизни:** как руководитель проекта, который не уходит домой, пока все члены команды не сдали свои части работы. Если один провалил задачу — остальным сообщают, что проект отменён, и они тоже прекращают работу.\n\n\u003Cdetails>\u003Csummary>Пример: ShutdownOnFailure и ShutdownOnSuccess\u003C\u002Fsummary>\n\n```java\n\u002F\u002F Проблема: без Structured Concurrency\nExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();\nFuture\u003CUser> userFuture = executor.submit(() -> fetchUser(id));\nFuture\u003CList\u003COrder>> ordersFuture = executor.submit(() -> fetchOrders(id));\n\u002F\u002F Если fetchOrders бросит исключение — fetchUser продолжает выполняться!\n\u002F\u002F Если основной поток прервётся — подзадачи «утекают»\n\n\u002F\u002F Решение: Structured Concurrency\ntry (var scope = new StructuredTaskScope.ShutdownOnFailure()) {\n    Subtask\u003CUser> user = scope.fork(() -> fetchUser(id));\n    Subtask\u003CList\u003COrder>> orders = scope.fork(() -> fetchOrders(id));\n\n    scope.join();           \u002F\u002F ждём завершения обеих задач\n    scope.throwIfFailed();  \u002F\u002F бросить исключение, если одна из задач упала\n\n    return new UserWithOrders(user.get(), orders.get());\n}\n\u002F\u002F При ошибке одной задачи — другая отменяется автоматически\n\n\u002F\u002F ShutdownOnSuccess — вернуть первый успешный результат\ntry (var scope = new StructuredTaskScope.ShutdownOnSuccess\u003CString>()) {\n    scope.fork(() -> fetchFromPrimary());\n    scope.fork(() -> fetchFromFallback());\n    scope.join();\n    return scope.result(); \u002F\u002F первый успешный\n}\n```\n\n\u003C\u002Fdetails>\n\n### Стратегии\n\n| Стратегия | Поведение | Когда использовать |\n|-----------|-----------|-------------------|\n| `ShutdownOnFailure` | Отменить все при первой ошибке | Параллельные зависимые запросы |\n| `ShutdownOnSuccess` | Вернуть первый успешный результат | Racing, fallback |\n\n### Частые ошибки\n\n- Не вызывать `join()` — без `join()` результаты недоступны и подзадачи могут утечь\n- Использовать вне try-with-resources — scope должен быть закрыт для гарантии завершения\n- Путать с `CompletableFuture.allOf()` — Structured Concurrency проще и безопаснее для fork-join паттерна\n\n### Как используется в 2026\n\n- Structured Concurrency финализирован и активно используется с Virtual Threads\n- Заменяет ручное управление `Future` + `ExecutorService` для параллельных запросов\n- В Spring-приложениях — для параллельного вызова нескольких микросервисов\n\n> **На собеседовании:** объясните проблему (утечка подзадач при ошибке или отмене), решение (жизненный цикл подзадач привязан к scope), и две стратегии. Частая ошибка — не понимать, зачем нужен try-with-resources для scope.","","junior",[15],"java-modern",[],null,{"title":19,"description":20,"ogTitle":19,"ogDescription":21,"keywords":22,"schemaAnswer":23,"featuredSnippetReady":24},"Records — что это и зачем? — Gymterview","Record — компактный способ объявления классов-носителей неизменяемых данных (data carriers). Компилятор автоматически генерирует конструктор, accessor-методы, `","Record — компактный способ объявления классов-носителей неизменяемых данных (data carriers). Компилятор автоматически ге",[15,13],"Record — компактный способ объявления классов-носителей неизменяемых данных (data carriers). Компилятор автоматически генерирует конструктор, accessor-методы, `equals()`, `hashCode()` и `toString()`.",true]