Многопоточное программирование. Многозадачность, основанная на потоках как минимальной единице диспетчеризации

Страницы работы

Фрагмент текста работы

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

Взаимодействия потоков в Java реализуются через вызовы предопределенных методов, которыми обладают все объекты.

Организация потоков

Один из потоков – «главный» начинает выполняться первым при запуске Java-программы. От него порождаются дочерние потоки. Главный поток является последним выполняющимся потоком. Программа завершается, когда главный поток останавливается.

Поток может быть создан на основе базового класса Thread  или реализации интерфейса Runnable. Класс Thread инкапсулирует ряд методов, которые помогают управлять потоками.

java.lang.Object

|

+--java.lang.Thread

Главный поток создается автоматически с именем main  и приоритетом 5 по умолчанию. Им можно управлять через Thread объект. Ссылку на него можно получить через статический метод static currentThread (  ), т.е. выполнить, например:

Threadtp = Thread.CurrentThread ( ) – возвращает ссылку на поток, в котором он вызывается. В дальнейшем эту объектную ссылку можно использовать для вызова методов в управлении потоками.

Например, установить новое имя потока при помощи (string).

Thread tp = Thread.CurrentThread ( )

System.ont.println («новоеимяпотока:» + tp.setName («New name»);.

Новое имя потока: Thread [Newname, 5,main], где NewName – новое имя потока;       5- приоритет, заданный по умолчанию.

main –имя группы потоков, которой принадлежит данный поток.

Группа потоков – структура данных, контролирующая состояние совокупности потоков в целом.

Создание нового потока

Самый простой способ создания – реализация интерфейса Runnable, который требует определения в классе реализации метода: public void run (  ); , устанавливающего в программе точку входа для запуска нового конкурирующего потока выполнения.

Пример:

// класс для создания нового (второго) потока.

class NewThread implements Runnable {Thread t;

NewThread (  )

{        // констр. для создания нового потока, создает

БЛОК1                                 //новый     DemoThread  поток

t=newThread (this, "DemoThread"); // новый поток t

System.out.println ("Дочерний поток: " + t );

t.start ( );             // стартовать поток

}                 

// точка  входа для второго потока.

public void run (  )

{        // тело нового потока

try {for (int i=3; i > 0; i--)

{System.out.println ("Дочернийпоток : "+ i);

 Thread.sleep (500);    // приостановить  на 500 милисекунд.

}        }

catch (InterruptedException е)

{        System.out.println ("Прерывание дочернего потока");

}

System.out.println ("Завершение дочернего потока");

}        }

//головная программа

class TreadDemo

{        public static void main(String args[])

          { new NewThread();

                    try     {

                                       for (int i=3;i>0;i--) {

System.out.println("Главный поток:Э " +i);

Thread.sleep(1000);

                              }

          }        catch (InterruptedException е)

{System.out.println ("Прерывание главного потока");

}

System.out.println ("Завершение главного потока");

}        }

Вывод программы:

Дочерний поток: Tread  [ Demo Thread, 5, main]

Главный поток 3

Дочерний поток 3

Дочерний поток 2

Главный поток 2

Дочерний поток 1

Завершение дочернего потока

Главный поток 1

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

,здесь за счет расчета  величины паузы (1000 и 500) обеспечивается завершение главного потока после дочернего.

Для реализации потока приложения расширением класса Thread необходимо внести следующие изменения в предыдущий пример. Вместо блок 1 (желтый фон) записать:


Class NewThread extends Thread

// создать новый (второй) поток используя конструкцию

NewThread()

{        superDemoThread»);     // метод super () вызывает //конструктор базового класса, его модификацию

// public Thread( String threadName)

system.out.println («дочерний поток:» + this);

start (  );    //стартовать поток

}

Обращение к методу super (“Demo Thread ”  ); вызывает следующую форму конструктора Tread:       

public Thread (String thread Name);  , где threadName – имя потока.

В данных примерах правильное завершение реализовывалось на основе расчета пауз. Такое решение не является эффективным средством синхронизации, хотя оператор sleep (int x), эффективен для организации прерывания процесса с целью передачи управления.

Для организации нескольких потоков необходимо предусмотреть в головной программк (main), зипуск несколько потоков, при помощи команд:

new NewThread(“1-йпоток”);   

new NewThread(“2-йпоток”);

…………………

newNewThread(“N-й поток”); //, где в кавычках указывается имя потока.

Кроме того, предусмотреть нужную последовательность их выполнения и гарантию завершения главного потока последним.

Поток Thread имеет ряд методов, которые могут быть переопределены внутри создаваемого потока. Обязательным для переопределения является только метод run();

Два метода потока Thread, позволяют определить закончился ли поток, это:

finalbooleanisAlive ();                  // возвращается true, если  поток выполняется

finalvoidjoin ();         // этот метод ждет завершения потока на котором он вызван, наиболее часто используемый . Этот метод выбрасывает исключение  throwsInterruptedException, для которого необходимо предусмотреть обработку.  Используя названные методы можно, например, организовать ожидание завершение дочерних потоков перед главным потоком.

Например, проверить выполняется ли поток можно следующим образом:

NewTreadob1 = newNewThread («Первый»);  //создание потока

Похожие материалы

Информация о работе