В некоторых сценариях мы должны дождаться завершения выполнения потока, прежде чем переходить к следующему шагу. Например, некоторым программам необходимо инициализировать некоторые ресурсы перед началом выполнения. В это время мы можем запустить поток специально для выполнения задачи инициализации и дождаться завершения задачи потока, прежде чем выполнять другие части.
Для этой цели класс Thread предоставляет нам метод join(). Когда мы вызываем этот метод с использованием объекта потока, вызывающий объект потока будет задержан до тех пор, пока вызываемый объект не завершит выполнение, прежде чем начать выполнение.
В этом разделе пример программы демонстрирует ожидание завершения метода инициализации перед выполнением других задач.
знай это
Выполните шаги, показанные ниже, чтобы завершить пример программы.
1. Создайте класс с именем DataSourcesLoader и реализуйте интерфейс Runnable. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
публичный класс DataSourcesLoader реализует Runnable {
2. Реализуйте метод run(), выведите на консоль сообщение, указывающее на начало выполнения, затем задержитесь на 4 секунды, а затем напечатайте на консоль сообщение, указывающее на окончание выполнения потока. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
@Override
общественный недействительный запуск () {
System.out.printf("Начало загрузки источников данных: %s/n",
новая дата());
пытаться {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
е.printStackTrace();
}
System.out.printf("Загрузка источников данных завершена: %s/n",
новая дата());
}
3. Создайте класс с именем NetworkConnectionsLoader и реализуйте интерфейс Runnable. Реализуйте метод run(). Код этого метода такой же, как и метод run() класса DataSourcesLoader, за исключением того, что он находится в режиме ожидания 6 секунд.
4. Реализуйте основной класс примера и реализуйте метод main(). Код выглядит следующим образом:
Скопируйте код кода следующим образом:
общественный класс Main {
public static void main(String[] args) {
5. Создайте объект DataSourcesLoader и объект Thread, чтобы начать его выполнение. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
DataSourcesLoader dsLoader = новый DataSourcesLoader ();
Поток thread1 = новый поток (dsLoader, «DataSourcesLoader»);
6. Создайте объект NetworkConnectionsLoader и объект Thread, чтобы начать его выполнение. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
NetworkConnectionsLoader ncLoader = новый NetworkConnectionsLoader ();
Поток thread2 = новый поток (ncLoader, «NetworkConnectionsLoader»);
7. Вызовите метод start() двух объектов Thread. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
поток1.start();
поток2.start();
8. Вызовите метод join(), чтобы дождаться завершения двумя потоками своих задач. Этот метод выдаст InterruptedException, поэтому перехватите это исключение. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
пытаться {
поток1.присоединиться();
поток2.присоединиться();
} catch (InterruptedException e) {
е.printStackTrace();
}
9. Выведите на консоль предложение, обозначающее окончание выполнения программы. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
System.out.printf("Main: Конфигурация загружена: %s/n",
новая дата());
10. Запустите программу и проверьте эффект выполнения.
знаю почему
При запуске этого примера программы мы видим, как два потока начинают свое выполнение. Сначала DataSourcesLoader завершает свое выполнение, затем NetworkConnectionsLoader завершает свое выполнение; На этом этапе основной поток продолжает свое выполнение, а затем выводит на консоль сообщение о завершении.
бесконечный
Java предоставляет два других перегруженных метода join():
Скопируйте код кода следующим образом:
присоединиться (длинные миллисекунды)
join(длинные миллисекунды, длинные нано)
Первый метод не ждет, пока вызываемый объект завершит задачу, а ожидает времени, указанного в параметре, прежде чем начать выполнение, например, если поток1 вызывает этот метод, поток1.join(1000), когда поток потока1 встречает один из; следующие условия будут продолжать выполняться:
1.thread2 завершает свое выполнение;
2. Через 1000 миллисекунд;
Когда одно из этих двух условий истинно, метод join() вернется и продолжит выполнение исходной задачи.
Второй метод очень похож на первый, за исключением того, что он имеет дополнительный параметр наносекундного времени.
Используйте доктрину
Эта статья переведена из «Книги по параллелизму Java 7» (Д Гуа Ге украл ее как «Коллекция примеров параллелизма Java7») и используется только в качестве учебных материалов. Его нельзя использовать в коммерческих целях без разрешения.
Небольшой успех
Полная версия примера кода, используемого в этом разделе.
Полный код класса DataSourcesLoader выглядит следующим образом:
пакет com.diguage.books.concurrencycookbook.chapter1.recipe6;
импортировать java.util.Date;
импортировать java.util.concurrent.TimeUnit;
/**
* Дата: 19 сентября 2013 г.
* Время: 09:15
*/
публичный класс DataSourcesLoader реализует Runnable {
@Override
общественный недействительный запуск () {
System.out.printf("Начало загрузки источников данных: %s/n",
новая дата());
пытаться {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
е.printStackTrace();
}
System.out.printf("Загрузка источников данных завершена: %s/n",
новая дата());
}
}
Полный код класса NetworkConnectionsLoader
Скопируйте код кода следующим образом:
пакет com.diguage.books.concurrencycookbook.chapter1.recipe6;
импортировать java.util.Date;
импортировать java.util.concurrent.TimeUnit;
/**
* Дата: 19 сентября 2013 г.
* Время: 09:21
*/
публичный класс NetworkConnectionsLoader реализует Runnable {
@Override
общественный недействительный запуск () {
System.out.printf("Начало загрузки источников данных: %s/n",
новая дата());
пытаться {
TimeUnit.SECONDS.sleep(6);
} catch (InterruptedException e) {
е.printStackTrace();
}
System.out.printf("Загрузка источников данных завершена: %s/n",
новая дата());
}
}
Полный код основного класса
Скопируйте код кода следующим образом:
пакет com.diguage.books.concurrencycookbook.chapter1.recipe6;
импортировать java.util.Date;
/**
* Дата: 19 сентября 2013 г.
* Время: 09:25
*/
общественный класс Main {
public static void main(String[] args) {
DataSourcesLoader dsLoader = новый DataSourcesLoader ();
Поток thread1 = новый поток (dsLoader, «DataSourcesLoader»);
NetworkConnectionsLoader ncLoader = новый NetworkConnectionsLoader ();
Поток thread2 = новый поток (ncLoader, «NetworkConnectionsLoader»);
поток1.start();
поток2.start();
пытаться {
поток1.присоединиться();
поток2.присоединиться();
} catch (InterruptedException e) {
е.printStackTrace();
}
System.out.printf("Main: Конфигурация загружена: %s/n",
новая дата());
}
}