[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-mnogopotochnost-dany-3-potoka-t1-t2-i-t3-kak-realizovat-vypolnenie-v-posledovatelnosti-t1-t2-t3":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":19,"progress":20,"seo":21},286,"dany-3-potoka-t1-t2-i-t3-kak-realizovat-vypolnenie-v-posledovatelnosti-t1-t2-t3",8,"mnogopotochnost","Многопоточность","🔀","Даны 3 потока Т1, Т2 и Т3. Как реализовать выполнение в последовательности Т1, Т2, Т3?","\u003C!-- grade: 3\u002F5 — ответ слишком краткий; добавлены варианты реализации с кодом -->\n\nСуществует несколько способов обеспечить последовательное выполнение потоков.\n\n**Способ 1: `Thread.join()` (самый простой)**\n\nМетод `join()` блокирует вызывающий поток до завершения целевого потока.\n\n```java\nThread t1 = new Thread(() -> System.out.println(\"T1\"));\nThread t2 = new Thread(() -> System.out.println(\"T2\"));\nThread t3 = new Thread(() -> System.out.println(\"T3\"));\n\nt1.start();\nt1.join(); \u002F\u002F Ждём завершения T1\n\nt2.start();\nt2.join(); \u002F\u002F Ждём завершения T2\n\nt3.start();\nt3.join(); \u002F\u002F Ждём завершения T3\n```\n\n**Способ 2: `join()` внутри потоков**\n\nКаждый поток вызывает `join()` на предыдущем:\n\n```java\nThread t1 = new Thread(() -> System.out.println(\"T1\"));\n\nThread t2 = new Thread(() -> {\n    try { t1.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }\n    System.out.println(\"T2\");\n});\n\nThread t3 = new Thread(() -> {\n    try { t2.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }\n    System.out.println(\"T3\");\n});\n\n\u002F\u002F Порядок запуска не важен!\nt3.start();\nt2.start();\nt1.start();\n```\n\n**Способ 3: `CountDownLatch`**\n\n```java\nCountDownLatch latch1 = new CountDownLatch(1);\nCountDownLatch latch2 = new CountDownLatch(1);\n\nThread t1 = new Thread(() -> {\n    System.out.println(\"T1\");\n    latch1.countDown();\n});\n\nThread t2 = new Thread(() -> {\n    try { latch1.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }\n    System.out.println(\"T2\");\n    latch2.countDown();\n});\n\nThread t3 = new Thread(() -> {\n    try { latch2.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }\n    System.out.println(\"T3\");\n});\n\nt3.start(); t2.start(); t1.start();\n```\n\n**Способ 4: `ExecutorService` с одним потоком**\n\n```java\nExecutorService executor = Executors.newSingleThreadExecutor();\nexecutor.submit(() -> System.out.println(\"T1\"));\nexecutor.submit(() -> System.out.println(\"T2\"));\nexecutor.submit(() -> System.out.println(\"T3\"));\nexecutor.shutdown();\n```\n\n`newSingleThreadExecutor()` гарантирует выполнение задач строго последовательно в порядке их подачи.\n\n> **На собеседовании** наиболее ожидаемый ответ — через `join()`. Но если упомянете `CountDownLatch` или `SingleThreadExecutor`, это покажет знание инструментов `java.util.concurrent`.","","junior",[15,16,17,18],"последовательность","потоки","Thread.join","concurrency",[],null,{"title":22,"description":23,"ogTitle":24,"ogDescription":25,"keywords":26,"schemaAnswer":31,"featuredSnippetReady":32},"Последовательное выполнение трёх потоков T1, T2, T3 в Java — Gymterview","Для последовательного выполнения потоков Т1, Т2, Т3 используется метод join(): Т3 вызывает Т2.join(), Т2 вызывает Т1.join().","Как выполнить потоки Т1, Т2, Т3 последовательно?","Запустите последний поток первым и используйте join() в обратном порядке: Т3 вызывает Т2.join(), Т2 вызывает Т1.join().",[27,28,29,30],"последовательность потоков Java","Thread.join пример","порядок выполнения потоков","T1 T2 T3 потоки","Используйте метод join(): запустите последний поток первым, затем вызывайте join() в обратном порядке — Т3 вызывает Т2.join(), а Т2 вызывает Т1.join(). Таким образом Т1 завершится первым, а Т3 последним.",true]