- •Многопоточность
- •Приоритеты потоков
- •Класс Thread и интерфейс Runnable
- •Главный поток
- •Расширение Thread
- •Выбор подхода
- •Использование методов isAlive() и join()
- •Приоритеты потоков
- •Синхронизация
- •Использование синхронизированных методов
- •Прерывание потоков
- •Оператор synchronized
- •Использование класса ReentrantLock.
Использование методов isAlive() и join()
Итак, главный поток должен быть последним завершающимся потоком. В предшествующих примерах это выполнялось вызовом метода sleep() в main() с достаточно длинной задержкой, чтобы гарантировать, что все дочерние потоки закончатся до завершения главного потока.
Существуют два других способа определения, закончился ли поток. Один из них позволяет вызывать метод isAlive() на потоке. Этот метод определен в Thread и его общая форма выглядит так:
final boolean isAlive()
Метод isAlive() возвращает true, если поток, на котором он вызывается — все еще выполняется. В противном случае возвращается false.
Другой способ ожидания завершения потока - вызов метода join() следующего формата:
final void join() throws InterruptedException
Этот метод ждет завершения потока, на котором он вызван. Дополнительные формы join() позволяют определять максимальное время ожидания завершения указанного потока.
Ниже показана улучшенная версия предшествующего примера, использующая join() и гарантирующая, что главный поток останавливается последним. Она также демонстрирует метод isAlive() (DemoJoin.java).
// Использование join() для ожидания окончания потока.
class NewThread implements Runnable
{
String name; // имя потока
Thread t;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("Новый поток: " + t);
t.start(); // старт потока
}
// Это точка входа потока.
public void run()
{ try
{
for(int i = 5; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println(name + " прерван.");
}
System.out.println(name + " завершен.");
}
}
class DemoJoin {
public static void main(String args[]) {
NewThread ob1 = new NewThread("Первый");
NewThread ob2 = new NewThread("Второй");
NewThread ob3 = new NewThread("Третий");
System.out.println("Первый поток выполняется: " + ob1.t.isAlive());
System.out.println("Второй поток выполняется: " + ob2.t.isAlive());
System.out.println("Третий поток выполняется: " + ob3.t.isAlive());
// ждать завершения потоков
try {
System.out.println("Ждите завершения потоков.");
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch (InterruptedException e) {
System.out.println("Прерывание главного потока");
}
System.out.println("Первый поток выполняется: " + ob1.t.isAlive());
System.out.println("Второй поток выполняется: " + ob2.t.isAlive());
System.out.println("Третий поток выполняется: " + ob3.t.isAlive());
System.out.println("Завершение главного потока.");
}
}
Пример вывода этой программы:
Новый поток: Thread[Первый,5,main]
Новый поток: Thread[Второй,5,main]
Новый поток: Thread[Третий,5,main]
Первый: 5
Первый поток выполняется: true
Второй поток выполняется: true
Третий поток выполняется: true
Ждите завершения потоков.
Третий: 5
Второй: 5
Первый: 4
Третий: 4
Второй: 4
Третий: 3
Первый: 3
Второй: 3
Третий: 2
Второй: 2
Первый: 2
Третий: 1
Первый: 1
Второй: 1
Первый завершен.
Третий завершен.
Второй завершен.
Первый поток выполняется: false
Второй поток выполняется: false
Третий поток выполняется: false
Завершение главного потока.
После возврата из join() потоки прекращают выполняться.
