Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шпори JAVA.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
178.34 Кб
Скачать

57.Класс Thread

клас Thread

Потік виконання в Java представляється екземпляром класу Thread. Для того , щоб написати свій потік виконання необхідно успадковуватися від цього класу іперевизначити метод run ( ) наприклад , 

public class MyThread extends Thread {

  public void run () {

   / / Деякий довгий дію , обчислення

   long sum = 0 ;

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

    sum + = i ;   }

   System.out.println ( sum ) ;  }}

Метод run ( ) містить дії , які повинні виконаються в новому потоці виконання.

Щоб запустити його , необхідно створити екземпляр класу - спадкоємця , і викликати

успадкований метод start ( ) , який повідомляє віртуальній машині , що необхідно

запустити новий потік виконання і почати в ньому виконувати метод run ( ) . 

MyThread t = new MyThread ();

t.start ();

Базові класи для роботи з потоками В результаті чого на консолі з'явиться результат: 499500

Коли метод run ( ) завершено ( зокрема , зустрілося вираз return ) потік виконання

зупиняється. Проте, ніщо не перешкоджає запису нескінченного циклу в цьому методі .

У результаті потік не перерве свого виконання , і буде зупинений тільки при завершенні роботи всього програми .

58. Інтерфейс Runnable

Описаний підхід володіє одним недоліком. Оскільки в Java відсутня

множинне спадкування , вимога успадковуватися від Thread може призвести до

конфлікту . Якщо ще раз подивитися на наведений вище приклад , то стане зрозуміле , що

спадкування вироблялося тільки з метою перевизначення методу run ( ) . Тому

пропонується більш простий спосіб створити свій потік виконання. досить

реалізувати інтерфейс Runnable , в якому оголошено тільки один метод - вже знайомий

void run ( ) . Запишемо приклад, наведений вище , за допомогою цього інтерфейсу: 

public class MyRunnable implements Runnable {

  public void run () {

   / / Деякий довгий дію , обчислення

   long sum = 0 ;

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

    sum + = i ;    }

   System.out.println ( sum ) ;

  }

}

Також незначно змінюється процедура запуску потоку :

 

Runnable r = new MyRunnable ();

Thread t = new Thread ( r ) ;

t.start ();

Якщо раніше об'єкт, що представляє сам потік виконання , і об'єкт з методом run ( ) ,

містить корисну функціональність , були об'єднані в одному екземплярі класу

MyThread , то тепер вони розділені. Який з двох підходів зручніше , можна вільно

вирішувати в кожному конкретному випадку.

Підкреслимо , що Runnable не є повною заміною класу Thread , оскільки створення

і запуск самого потоку виконання можливо тільки через метод Thread.start ( ) .

60. Потоки-демони

Демон - потоки дозволяють описувати фонові процеси , які потрібні тільки для

обслуговування основних потоків виконання і не можуть існувати без них. Для роботи з цією властивістю існують методи setDaemon ( ) і isDaemon ( ) .

Розглянемо наступний приклад:

public class ThreadTest implements Runnable {

/ / Окрема група , в якій будуть

 / / Знаходиться все потоки ThreadTest

public final static ThreadGroup GROUP =

 new ThreadGroup ( " Daemon demo " ) ;

 / / Стартове значення ,

 / / Вказується при створенні об'єкта

private int start ;

public ThreadTest ( int s ) {

   start = ( s % 2 == 0 ) ? s : s +1 ;

  new Thread ( GROUP , this , " Thread" + start ) . start ();

 }

 public void run () {

  / / Починаємо зворотний відлік

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

   try {

    Thread.sleep ( 300 ) ;

   } Catch ( InterruptedException e ) { }

   / / По досягненню середини породжуємо новий

   / / Потік з половинним початковим значенням

   if ( start > 2 && i == start / 2 ) {

    new ThreadTest ( i ) ;} }}

public static void main ( String s []) {

   new ThreadTest ( 16 ) ;

   new DaemonDemo (); }}

public class DaemonDemo extends Thread {

 public DaemonDemo () {

  super ( " Daemon demo thread " ) ;

  setDaemon ( true ) ;

  start ();

 }

 

 public void run () {

  Thread threads [] = new Thread [ 10 ] ;

  while ( true ) {

   / / Отримуємо набір всіх потоків з

   / / Тестової групи

   int count = ThreadTest.GROUP.activeCount ();

   if ( threads.length < count ) threads =

Демон - потоки Стор. 9 з 24

Програмування на Java

Rendered by www.RenderX.comnew Thread [ count +10 ] ;

   count = ThreadTest.GROUP.enumerate ( threads ) ;

   / / Роздруковуємо ім'я кожного потоку

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

    System.out.print ( threads [ i ] . GetName ( ) + " , " ) ;

   }

   System.out.println ();

   try {

    Thread.sleep ( 300 ) ;

   } Catch ( InterruptedException e ) { }} }} У цьому прикладі відбувається наступне . Потоки ThreadTest мають деякий стартове

значення , яке передається їм при створенні . У методі run ( ) це значення

послідовно зменшується. При досягненні половини від початкової величини

породжується новий потік з удвічі меншим початковим значенням. За вичерпанні лічильника потік зупиняється. Метод main ( ) породжує перший потік зі стартовим значень 16 . В ході програми , значить , будуть додатково породжені потоки зі значеннями 8 , 4 , 2.За цим процесом спостерігає демон - потік DaemonDemo . Цей потік регулярно отримує список всіх існуючих потоків ThreadTest і роздруковує їх імена для удобстванаблюденія .

Результатом програми буде :

Thread 16 , Thread 16 , Thread 16 , Thread 16 , Thread 16 , Thread 16 , Thread 16 , Thread 16 , Thread 16 , Thread 16 , Thread 8 , Thread 16 , Thread 8 , Thread 16 , Thread 8 , Thread 16 , Thread 8 , Thread 16 , Thread 8 , Thread 16 , Thread 8 , Thread 4 , Thread 16 , Thread 8 , Thread 4 ,

Thread 8 , Thread 4 , Thread 4 , Thread 2 , Thread 2 , Незважаючи на те , що демон - потік ніколи не виходить з методу run ( ) , віртуальна машина припиняє роботу як тільки все не - демон - потоки завершуються . У прикладі використовувалося кілька додаткових класів і методів , які ще не були розглянуті:

• клас ThreadGroupВсе потоки знаходяться в групах , що представляються екземплярами класу ThreadGroup .

Група вказується при створенні потоку . Якщо група не була зазначена , то потік

поміщається в ту ж групу , де знаходиться потік , що породив його .

Методи activeCount ( ) і enumerate ( ) повертають кількість і повний список

відповідно всіх потоків в групі.

• sleep ( )

Цей статичний метод класу Thread призупиняє виконання поточного потоку

на вказану кількість мілісекунд. Зверніть увагу , що метод вимагає обробки

виключення InterruptedException . Він пов'язаний з можливістю повернути до роботи метод ,

який призупинив свою роботу. Наприклад , якщо потік знаходиться в виконанні

методу sleep ( ) , тобто нічого не виконує протягом зазначеного періоду часу ,

то його можна вивести з цього стану , викликавши метод interrupt ( ) з іншого потоку

виконання . В результаті , метод sleep ( ) перерветься винятком InterruptedException .

Крім методу sleep ( ) існує ще один статичний метод yield ( ) без параметров.Когда потік викликає його , він тимчасово призупиняє свою роботу і дозволяє відпрацювати іншим потокам. Один з методів обов'язково повинен застосовуватися внутрібесконечних циклів очікування , інакше є ризик , що такий нічого не робить потік серйозно загальмує роботу інших потоків .

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]