Java -практические советы

         

Класс Thread

В классе Thread семь конструкторов:

  • Thread(ThreadGroup group, Runnabie target, String name)

    — создает ПОД-процесс с именем name, принадлежащий группе group и выполняющий метод run о объекта target. Это основной конструктор, все остальные обращаются к нему с тем или иным параметром, равным null;
  • Thread () — создаваемый подпроцесс будет выполнять свой метод run ();
  • Thread(Runnabie target);
  • Thread(Runnabie target, String name);
  • Thread(String name);
  • Thread(ThreadGroup group, Runnabie target);
  • Thread(ThreadGroup group, String name).

Имя подпроцесса name не имеет никакого значения, оно не используется, виртуальной машиной Java и применяется только для различения подпроцессов в программе.

После создания подпроцесса его надо запустить методом start (). Виртуальная машина Java начнет выполнять метод run () этого объекта-подпроцесса.

Подпроцесс завершит работу после выполнения метода run (). Для уничтожения объекта-подпроцесса вслед за этим он должен присвоить значение null.

Выполняющийся подпроцесс можно приостановить статическим методом sleep (long ms) на ms миллисекунд. Этот метод мы уже использовали в предыдущих главах. Если вычислительная система может отсчитывать наносекунды, то можно приостановить подпроцесс с точностью до наносекунд методом sleep(long ms, int nanosec).

В листинге 17.1 приведен простейший пример. Главный подпроцесс создает два подпроцесса с именами Thread i и Thread 2, выполняющих один и тот же метод run (). Этот метод просто выводит 20 раз текст на экран, а затем сообщает о своем завершении.

Листинг 17.1. Два подпроцесса, запущенных из главного подпроцесса

class OutThread extends Thread{ 

private String msg; 

OutThread(String s, String name){

super(name); msg = s; 

public void run()

{

for(int i = 0; i < 20; i++){ 

// try{

// Thread.sleep(100); 

// }catch(InterruptedException ie){}

System.out.print(msg + " "); 

System.out.println("End of " + getName()); 

} class TwoThreads{

public static void main(String[] args){

new OutThread("HIP", "Thread 1").start(); 

new OutThread("hop", "Thread 2").start(); 

System.out.println(); 

}

На рис. 17.1 показан результат двух запусков программы листинга 17.1. Как видите, в первом случае подпроцесс Thread i успел отработать полностью до переключения процессора на выполнение второго подпроцесса. Во втором случае работа подпроцесса Thread i была прервана, процессор переключился на выполнение подпроцесса Thread 2, успел выполнить его полностью, а затем переключился обратно на выполнение подпроцесса Thread i и завершил его.

Рис. 17.1. Два подпроцесса работают без задержки

Уберем в листинге 17.1 комментарии, задержав тем самым выполнение каждой итерации цикла на 0,1 секунды. Пустая обработка исключения InterruptedException означает, что мы игнорируем попытку прерывания работы подпроцесса. На рис. 17.2 показан результат двух запусков программы. Как видите, процессор переключается с одного подпроцесса на другой, но в одном месте регулярность переключения нарушается и ранее запущенный подпроцесс завершается позднее.

Рис. 17.2. Подпроцессы работают с задержкой

Как же добиться согласованности, как говорят, синхронизации (synchronization) подпроцессов? Обсудим это ниже, а пока покажем еще два варианта создания той же самой программы.

В листинге 17.2 приведен второй вариант той же программы: сам класс TwoThreads2 является расширением класса Thread, а метод run () реализуется прямо в нем. 

Листинг 17.2. Класс расширяет Thread

class TwoThreads2 extends Thread{ 

private String msg; 

TwoThreads2(String s, String name){

super(name); msg = s; 

public void run(){

for(int i = 0; i < 20; i++){ 

try{

Thread.sleep(100); 

}catch(InterruptedException ie){} 

System.out.print(msg + " "); 

}

System.out.println("End of " + getName()); 

public static void main(String[] args)(

new TwoThreads2("HIP", "Thread 1").start(); 

new TwoThreads2("hop", "Thread 2").start(); 

System.out.println(); 

}

Третий вариант: класс TwoThreads3 реализует интерфейс Runnabie. Этот вариант записан в листинге 17.3. Здесь нельзя использовать методы класса Thread, но зато класс TwoThreads3 может быть расширением другого класса. Например, можно сделать его апплетом, расширив класс Applet или JAppiet.

Листинг 17.3. Реализация интерфейса Runnabie

class TwoThreadsS implements Runnabie{ 

private String msg; 

TwoThreads3(String s){ msg = s; } 

public void run(){

forfint i = 0; i < 20; i++){ 

try{

Thread.sleep(100); 

}catch(InterruptedException ie){} 

System.out.print(msg + " "); 

}

System.out.println("End of thread."); 

public static void main (String[] args){

new Thread(new TwoThreads3("HIP"), "Thread 1").start (); 

new Thread(new TwoThreads3("hop"), "Thread 2").start (); 

System.out.println(); 

}

Чаще всего в новом подпроцессе задаются бесконечные действия, выполняющиеся на фоне основных действий: проигрывается музыка, на экране вращается анимированный логотип фирмы, бежит рекламная строка. Для реализации такого подпроцесса в методе run о задается бесконечный цикл, останавливаемый после того, как объект-подпроцесс получит значение null.

В листинге 17.4 показан четвертый вариант той же самой программы, в которой метод runt) выполняется до тех пор, пока текущий объект-подпроцесс th совпадает с объектом до, запустившим текущий подпроцесс. Для прекращения его выполнения предусмотрен метод stop (), к которому обращается главный подпроцесс. Это стандартная конструкция, рекомендуемая документацией J2SDK. Главный подпроцесс в данном примере только создает объекты-подпроцессы, ждет одну секунду и останавливает их.

Листинг 17.4. Прекращение работы подпроцессов

class TwoThreadsS implements Runnabie{ 

private String msg; 

private Thread go; 

TwoThreadsS(String s){ 

msg = s;

go = new Thread(this); 

go.start(); 

public void run(){

Thread th = Thread.currentThread(); 

while(go == th){ 

try{

Thread.sleep(100); 

}catch(InterruptedException ie){} 

System.out.print(msg + " "); 

}

System.out.println("End of thread."); 

public void stop(){ go = null; }

public static void main(String[] args){ 

TwoThreadsS thl = new TwoThreadsS("HIP"); 

TwoThreadsS th2 = new TwoThreadsS("hop"); 

try{

Thread.sleep(1000); 

}catch(InterruptedException ie){} 

thl.stop(); th2.stop(); 

System.out.printlnf); 

}

 

Начало
Содержание раздела