Java Многопоточность метод Join

введите сюда описание изображения

Подскажите пожалуйста, начал проходить многопоточку. Правильно ли я понял суть метода join().

Определение. Нестатический метод класса Thread join() приостановит выполнение текущего потока до тех пор, пока другой поток не закончит свое выполнение.

Грубо говоря у меня сейчас есть два треда.(1,2). Допустим я хочу чтобы в начале выполнился тред1. Я вызываю у него метод tr1.join(). Что происходит в данный момент? Как я понял останавливается Main thread, далее он ждет пока выполнится тред под номером 1 и только потом опять запускается main thread и уже идет выполнение треда 2. Верно? А если я допустим хочу наоборот, чтобы в начале выполнился тред 2, а затем тред 1(как на картинке). Я вызываю у треда 2 метод join, но в моем коде почему не получается уже так и он работает в хаотичном порядке. Получается если я просто куски кода меняю местами(thread1 и thread2 тогда работает). Код приложу ниже объясните в чем ошибка?

Один класс выводит цвета, другой класс счетчик.

public class Main {

    public static void main(String[] args) {

        ThreadColors threadColors1 = new ThreadColors();
        threadColors1.start();
       


        Thread countThread2 = new Thread(new countThread());
        countThread2.start();
        try {
            countThread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        System.out.println("Finish");


    }
}
public class ThreadColors extends Thread {

    enum colors{
        GREEN,RED,WHITE,BLACK,YELLOW;
    }

    @Override
    public void run() {

        colors[] colorsArray = colors.values();

        for(colors typeColor : colorsArray) {

            System.out.println(typeColor);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }

}
public class countThread implements Runnable {
    @Override
    public void run() {

        for (int i = 0; i < 10 ; i++) {
            System.out.println("I:" + i);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Ответы (1 шт):

Автор решения: S.H.

Когда Вы создаётё тред в своём коде, Вы его неявно стартуете, так как при создании треда передаёте ему ту процедуру, которая должна в этом треде выполняться.

Когда вы говорите треду join() - это означает "а теперь надо постоять и подождать, пока процедура в треде выполнится до конца и сделает return".

Соответственно, есть 2 стратегии:

  1. Последовательное выполнение процедур в отдельном потоке. Статруем первый поток, джоинимся в него. Когда выполнение продолжилось - это значит, что процедура, котрую Вы сказали выполнить в отдельном потоке, "доиграла до конца". Потом создаём второй поток и даём ему на выполнение вторую процедуру. Опять ждём её завершения при помощи join.

Если Вы придерживаетесь этой стратегии, то, чтобы поменять порядок выполнения, надо поменять порядок создания тредов. И создавать второй только после того, как отработает join у первого. При этом никакого параллельного выполнения нет, это просто последовательный запуск процедур в отдельном потоке.

  1. Настоящее параллельное выполнение. Создаём сразу два потока. Только потом вызываем у них join'ы. Потоки будут "молотить" параллельно. Соответственно, выполнение основного кода продолжится, когда обе процедуры отработают.

при этом по большому счету от порядка, в котром Вы будете вызывать join'ы - мало что зависит. Процедуры бегут параллельно и "наперегонки".

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

Теперь поменяем порядок джоинов. Сначала ждем отработки долгой проуедуры. Вот мы из неё вернулись в основной поток, к этому времени быстрая уже отработала, поэтому строка с попыткой заджоиниться в быструю - отработает мгновенно, так как сама процедура уже выполнилась, и джоин в неё - это чистая формальность.

→ Ссылка