По идее метода join()
, если я правильно его понимаю, он должен передавать управление программой тому потоку, на объекте которого был вызван, в то время как тот поток который этот вызов произвел, должен ждать.
Однако, если мы имеем несколько объектов потока, для которых идут вызовы метода join()
подряд, то второй тоже запускается.
То есть, методе main
мы имеем такой код:
try {
thread01.join();
thread02.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
То по логике, сразу после выполнения вызова thread01.join();
, метод main
должен был остановиться и ждать пока thread01
не вернет ему управление программой, но логирование показывает, что вместо этого, он выполняет еще и thread02.join();
и только этого переходит в режим ожидания.
Почему так?
Это что означает, что метод join()
, срабатывает только в тех случаях, когда после него не идет еще один join()
, или тут блок try
, имеет какой-то особый смысл? Помогите пожалуйста разобраться.
Полный код потоков:
public class CounterOfSpace {
private int counterOfSpaces;
private int counterOfWords;
private String text;
private Thread thread01;
private Thread thread02;
public CounterOfSpace(String text) {
this.text = text;
}
void startAll() {
System.out.println("Start program");
calcWords();
calcSpaces();
thread01.start();
thread02.start();
try {
thread01.join();
thread02.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Finish program");
}
private void calcSpaces() {
thread01 = new Thread(new Runnable() {
@Override
public void run() {
if (text.length() == 0) return;
for (char c : text.toCharArray()) {
if (c == ' ') {
counterOfSpaces++;
System.out.println("counterOfSpaces "+counterOfSpaces);
}
}
}
});
}
private void calcWords() {
thread02 = new Thread(new Runnable() {
@Override
public void run() {
if (text.length() == 0) return;
String[] words = text.split(" ");
for (String word : words) {
if (!word.equals(" ")) {
counterOfWords++;
System.out.println("counterOfWords "+counterOfWords);
}
}
}
});
}
}
По идее метода join(), если я правильно его понимаю, он должен передавать управление программой тому потоку,
Это не совсем корректно, поток должен уходить в спящее состояние, а вот кому отдать управление решает шедулер.
Однако, если мы имеем несколько объектов потока, для которых идут вызовы метода join() подряд, то второй тоже запускается.
Что никак не противоречит парадигме. В данном случае мы имеем три истории с двумя точками синхронизации:
Main Thread1 Thread2
<init> <init> <init>
running running? finished? running? finished?
join t1 finished running? finished?
join t2 finished finished
Данный код гарантирует, что после завершения t1.join поток t1 будет завершен, но не гарантирует, что он не завершится до вызова t1.join, что очевидно и происходит в этом случае. К моменту вызова t1.join поток t1 может быть в любом состоянии, даже если ему приходится считать тяжелые данные продолжительное время - формально это разрешено, хоть на практике такое будет встречаться нечасто. Вкупе с
логирование показывает
это говорит о том, что, скорее всего, поток просто очень быстро заканчивает работу, а вы принимаете это за несоответствующий спецификации феномен. В таких проблемах не стоит полагаться на логирование, потому что его синхронизационные отношения по отношению к основной программе туманны, и для меня не было бы неожиданным несоблюдение порядка строчек в выводе или длительные (относительно происходящих в программе процессов) задержки при выводе. Также стоит умеренно полагаться на временные замеры подобных вещей, потому что стандартный источник времени может быть не монотонным и возвращать меньшие значения на последующие вызовы, в результате чего будет выглядеть, будто программа выполняется в обратном порядке.
При желании можно заглянуть в исходный код Thread и увидеть, что join реализован через wait и защищен isAlive-гардами от случайных пробуждений, поэтому метод join вернет не раньше, чем поток перестанет возвращать true на isAlive.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Добрый деньЯ учусь программировать приложения под андроид и в одной из книг нашел обучающий мануал - создание приложения прогноза погоды
По rtp поступает массив данных в байтахИзвестно, что данные в формате g729
Не понятно как сформировать запрос к базе Elasticsearchна официальном сайте пример запроса