Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Практикум по объектно-ориентированному программированию..pdf
Скачиваний:
25
Добавлен:
05.02.2023
Размер:
3.39 Mб
Скачать

132

Если в программе используется несколько дочерних потоков и надо, чтобы

главный поток завершался после дочерних, то для каждого дочернего потока

надо вызвать метод join().

Реализация интерфейса Runnable во многом аналогична переопределе-

нию класса Thread. Мы его уже рассмотрели ранее.

4.5.3 Завершение потока

Особо следует остановиться на механизме завершения потока. Во всех

примерах выше потоки завершались после выполнения последней операции. Од-

нако нередко имеет место и другая организация потока, и тогда мы также долж-

ны предусмотреть механизм завершения потока.

· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

В Java существуют средства для принудительного завершения

потока. В частности, метод Thread.stop() завершает поток неза-

медлительно после своего выполнения. Однако этот метод, а также

Thread.suspend(), приостанавливающий поток, и Thread.re-

sume(), продолжающий выполнение потока, были объявлены уста-

ревшими, и их использование отныне крайне нежелательно. Дело в

том, что поток может быть «убит» во время выполнения операции,

обрыв которой на полуслове оставит некоторый объект в неправиль-

ном состоянии, что приведет к появлению трудноотлавливаемой и

случайным образом возникающей ошибки.

· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

Вместо принудительного завершения потока применяется схема, в которой

каждый поток сам ответственен за свое завершение. Поток может остановиться

либо тогда, когда он закончит выполнение метода run() (main() – для глав-

ного потока), либо по сообщению из другого потока.

Как правило, это делается с помощью опроса логической переменной. И

если она равна, например, false, то поток завершает бесконечный цикл и за-

канчивает свое выполнение. Изменим наш TestThread:

class TestRunnable implements Runnable { private boolean isActive;

void disable(){ isActive=false;

}

TestRunnable(){

133

isActive = true;

}

public void run(){

System.out.printf("Поток %s начал работу... \n", Thread.currentThread().getName());

int counter=1; // счетчик циклов while(isActive){

System.out.println("Цикл " + counter++);

try{ Thread.sleep(500);

}

 

catch(InterruptedException

e){

System.out.println("Поток прерван");

}

}

System.out.printf("Поток %s завершил работу...\n", Thread.currentThread().getName());

}

}

Переменная isActive указывает на активность потока. С помощью метода disable() мы можем сбросить состояние этой переменной. Теперь используем этот класс:

public class Main {

public static void main(String[] args) { System.out.println("Главный поток начал работу..."); TestRunnable tThread = new TestRunnable();

new Thread(tThread,"TestThread").start();

try{

 

 

Thread.sleep(1100);

 

 

tThread.disable();

 

 

Thread.sleep(1000);

 

 

} catch(InterruptedException

e){

 

System.out.println("Поток прерван");

 

}

 

 

System.out.println("Главный поток

завершил работу...");

}

 

 

}

 

 

134

Вначале запускается дочерний поток:

new Thread(tThread,"TestThread").start();

Затем на 1100 миллисекунд останавливаем главный поток и потом вызываем метод tThread.disable(), который переключает в потоке флаг isActive. И дочерний поток завершается.

Консольный вывод представлен на рисунке 4.18.

Рис. 4.18 – Пример прерывания потока

4.5.4 Управление приоритетами

Каждый поток в системе имеет свой приоритет.

· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

Приоритет потоков – это некоторое число в объекте по-

тока, более высокое значение которого означает больший приоритет.

· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

Система в первую очередь выполняет потоки с большим приоритетом, а потоки с меньшим приоритетом получают процессорное время только тогда, когда более привилегированные потоки простаивают.

Потоку можно назначить приоритет от 1 (MIN_PRIORITY) до 10 (MAX_PRIORITY) с помощью метода setPriority(int). Получить значение приоритета можно с помощью метода getPriority().

· · · · · · · · · · · · · · · · · · · · · · · · ·

 

Пример · · · · · · · · · · · · · · · · · · · · · · · · ·

 

 

 

class TestThread extends Thread {

 

TestThread(String name){ super(name);

}

 

135

@Override

 

public

void run(){

for (int i = 0; i < 10; i++){ System.out.println(getName() + " " + i); try {

Thread.sleep(0);//попробовать sleep(1000);

}

catch (InterruptedException e) { System.err.print("Error" + e); }

}

}

}

Далее выставим приоритеты потокам:

public class Main {

public static void main(String[] args) { TestThread min = new TestThread("Min");//1 TestThread max = new TestThread("Max");//10 TestThread norm = new TestThread("Norm");//5 min.setPriority(Thread.MIN_PRIORITY); max.setPriority(Thread.MAX_PRIORITY); norm.setPriority(Thread.NORM_PRIORITY); min.start();

norm.start(); max.start();

}

}

· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

Поток с более высоким приоритетом в данном случае, как правило, монополизирует вывод на консоль (рис. 4.19).