public class Join1 {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
System.out.print("EnterValue:");
try {
System.in.read();
} catch (Exception ex) {}
System.out.println("Thread Finished.");
}
};
System.out.println("Starting Thread");
t.start();
System.out.println("Joining");
try {
t.join();
} catch (Exception ex) {}
System.out.println("Main Finished.");
}
}
Выход
Начальный поток
Присоединение
Введите значение:
Тема завершена
Главная Готовая
public class Join2 {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
System.out.println("EnterValue:");
try {
System.in.read();
} // thread blocked
catch (Exception ex) {}
System.out.println("Thread Finished.");
}
};
System.out.println("Starting Thread");
t.start();
try {
Thread.sleep(2000);
} catch (Exception e) {}
System.out.println("No Join");
System.out.println("Main Finished.");
}
}
Выход
Начальный поток
Введите значение:
Нет присоединения
Главная Готовая
3 (вход)
Тема завершена
Я не понимаю порядок некоторых из этих выходных данных. Например, в Join2, почему он выводит готовые строки в основном, прежде чем вы вводите свое значение?
Поскольку потоки не блокируют основную программу, они находятся в отдельных потоках, которые не блокируются.
Кроме того, я настоятельно рекомендую не принимать исключения (catch (Exception ex) {}). вы должны, как минимум, сделать ex.printStackTrace(). Это может даже способствовать возникновению вашей проблемы (у нас нет возможности узнать).
Это из заметок учителя. Я просто хочу знать, почему порядок вывода такой, как есть
@JohnBanter Я бы посоветовал вам изучить, что такое потоки и как они работают. Я сказал вам почему в моем последнем комментарии. Думайте о каждом потоке как о его собственной независимой подпрограмме, созданные вами потоки не мешают завершению основного потока. Из-за этого он завершит работу в основном потоке и будет ожидать ввода в созданные вами.




Единственное различие в двух приведенных примерах - это метод, вызываемый после запуска потока с t.start().
Join1.java вызывает Thread.join(), который, судя по документации, говорит: «Ожидает, пока этот поток умрет». Таким образом, только после завершения метода выполнения потока (после завершения System.in.read()) выполняется «Main Finished». Распечатать"
Join2.java вызывает Thread.sleep(2000), который приостанавливает поток на 2000 миллисекунд. Попробуйте закомментировать эту строку и посмотреть результат. Кроме того, обратите внимание, что программа не закрывается после того, как напечатает «Main Finished». Поток все еще ожидает ввода.
TL; DR;
Thread.join() делает основную паузу, пока этот поток не завершится.
Thread.sleep(2000) приостанавливает основной поток только на 2 секунды перед продолжением, другой поток продолжает выполняться.
Re, «... приостанавливает поток» (или «блокирует поток», или «засыпает (sic.) Поток» и т. д.). Некоторые из этих слов являются камнем преткновения для новичков, которые еще не совсем поняли концепции. Иногда они получают это быстрее, если вы говорите: «Thread.sleep(2000)ничего не делает, но подождите две секунды». или «t.join()ничего не делает, но дождаться завершения потока t». Последний особенно полезен, потому что многие новички откуда-то получают ошибочное представление о том, что t.join() выполняет что-нибудь для потока t.
Думайте о потоках как о параллельных выполнениях. К тому времени, когда вы вернетесь из .start () в основной поток, новый поток будет свободен, хорошо. Но в Join2 вы не говорите основному потоку ждать завершения потока t. Так что за 2 секунды он проходит мимо сна.
Что мешает
mainзакончить пример 2?