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 шт):
Когда Вы создаётё тред в своём коде, Вы его неявно стартуете, так как при создании треда передаёте ему ту процедуру, которая должна в этом треде выполняться.
Когда вы говорите треду join() - это означает "а теперь надо постоять и подождать, пока процедура в треде выполнится до конца и сделает return".
Соответственно, есть 2 стратегии:
- Последовательное выполнение процедур в отдельном потоке. Статруем первый поток, джоинимся в него. Когда выполнение продолжилось - это значит, что процедура, котрую Вы сказали выполнить в отдельном потоке, "доиграла до конца". Потом создаём второй поток и даём ему на выполнение вторую процедуру. Опять ждём её завершения при помощи join.
Если Вы придерживаетесь этой стратегии, то, чтобы поменять порядок выполнения, надо поменять порядок создания тредов. И создавать второй только после того, как отработает join у первого. При этом никакого параллельного выполнения нет, это просто последовательный запуск процедур в отдельном потоке.
- Настоящее параллельное выполнение. Создаём сразу два потока. Только потом вызываем у них join'ы. Потоки будут "молотить" параллельно. Соответственно, выполнение основного кода продолжится, когда обе процедуры отработают.
при этом по большому счету от порядка, в котром Вы будете вызывать join'ы - мало что зависит. Процедуры бегут параллельно и "наперегонки".
Пускай вы вызвали join первым у той процедуры, котрая отработает быстрее. Тогда произойдет переход к следующему джоину, и между этим переходом и завершением второго потока будет пауза. Грубо говоря, вы заметите, что первая процедура отработала быстрее.
Теперь поменяем порядок джоинов. Сначала ждем отработки долгой проуедуры. Вот мы из неё вернулись в основной поток, к этому времени быстрая уже отработала, поэтому строка с попыткой заджоиниться в быструю - отработает мгновенно, так как сама процедура уже выполнилась, и джоин в неё - это чистая формальность.
