Использование методов isAlive() и join(). Иногда необходимо, чтобы главный поток завершался последним.
Скачать исходники для статьи можно ниже
В предыдущих примерах это обеспечивается вызовом метода sleep()
из метода main() с задержкой, достаточной для того, чтобы гарантировать, что все дочерние потоки завершатся раньше главного. Однако это неудовлетворительное решение, которое вызывает серьезный вопрос: как один поток может знать о том, что другой завершился?
К счастью, класс Thread предлагает средство,которое дает ответ на этот вопрос.
Существует два способа определить, что поток был завершен.
Во-первых, вы можете вызвать метод isAlive() для этого потока. Этот метод определен в классе Thread, и его общая форма такова:
final Boolean isAlive()
Метод isAlive() возвращает значение true, если поток, для которого он вызван, еще выполняется. В противном случае он возвращает значение false.
Во-вторых, существует метод, который вы будете использовать чаще, чтобы дождаться завершения потока, а именно — метод join():
final void join() throws InetrruptedException
Этот метод ожидает завершение потока, для которого он вызван. Его имя отражает концепцию, что вызывающий поток ожидает, когда указанный поток присоединится к нему.
Ниже приведен пример, использующий метод join() для гарантии того, чтобы главный поток завершился последним. Здесь также демонстрируется применение метода isAlive():
// Применение 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 obi = new NewThread("Одни"); NewThread ob2 = new NewThread("Два"); NewThread ob3 = new NewThread("Три"); System.out.println("Поток Один запущен: "+ obi.t.isAlive()); System.out.println("Поток Два запущен: "+ ob2.t.isAlive()); System.out.println("Поток Три запущен: "+ оbЗ.t.isAlive()); // ожидать завершения потоков try { System.out.println("Ожидание завершения потоков."); obi.t.join(); ob2.t.join(); ob3.t.join(); } catch (InterruptedException e) { System.out.println("Главный поток прерван"); } System.out.println("Поток Один запущен: "+ obi.t.isAlive()); System.out.println("Поток Два запущен: "+ ob2.t.isAlive()); System.out.println("Поток Три запущен: "+ оЬЗ.t.isAlive()); System.out.println("Главный поток завершен."); } }
Пример вывода этой программы показан ниже (ваш вывод может отличаться,
в зависимости от конкретной среды исполнения)
.
Новый поток: Thread[Одни,5,main]
Новый поток: Thread[Два,5.main]
Новый поток: Thread[Три,5,main]
Поток Один запущен: true
Поток Два запущен: true
Поток Три запущен: true
Ожидание завершения потоков.
Один: 5
Два: 5
Три: 5
Один: 4
Два: 4
Три: 4
Один: 3
Два: 3
Три: 3
Один: 2
Два: 2
Три: 2
Один: 1
Два: 1
Три: 1
Два завершен.
Три завершен.
Один завершен.
Поток Один запущен: false
Поток Два запущен: false
Поток Три запущен: false
Главный поток завершен.
Как видите,после того, как вызовы метода join() вернут управление,
потоки прекращают работу.