Планування потоків

Java може працювати як на однопроцесорних, так і на багатопроцесорних компютерах, в однопотокових і багатопоточних системах, так що відносно потоків даються лише загальні гарантії Ви можете бути впевнені в тому, що здійсненний (runnable) потік з найвищим пріоритетом буде працювати і що всі потоки з тим же пріоритетом отримають деяку частку процесорного часу Функціонування потоків з нижчим пріоритетом гарантується лише в разі блокування всіх потоків з вищим пріоритетом / Читачеві слід відрізняти блокування обєкта (lock), про яку йшлося вище, від блокування потоку (block) Термінологія, що склалася у вітчизняній літературі, може стати джерелом непорозумінь – Прямуючи перев / Насправді не виключено, що потоки з нижчим пріоритетом будуть працювати і без таких рішучих заходів, але покладатися на це не можна

Потік називається заблокованим, Якщо він припинений або виконує заблоковану функцію (системну або функцію потоку) У випадку блокування потоку Java вибирає здійсненний потік з найвищим пріоритетом (або один з таких потоків, якщо їх декілька) і починає його виконання

Runtime-система Java може призупинити потік з найвищим пріоритетом, щоб дати попрацювати потоку з тим же пріоритетом, – це означає, що всі потоки, що володіють найвищим пріоритетом, з часом виконуються Проте це навряд чи можна вважати серйозною гарантією, оскільки з часом – поняття широке Пріоритетами слід користуватися лише для того, щоб вплинути на політику планування для підвищення ефективності Не варто покладатися на пріоритет потоків, якщо від цього залежить правильність роботи алгоритму

Початковий пріоритет потоку збігається з пріоритетом того потоку, який створив його Для установки пріоритету використовується метод setPriority з аргументом, значення якого лежить між константами MIN_PRIORITY і MAX_PRIORITY класу Thread Стандартний пріоритет для потоку за замовчуванням дорівнює NORM_PRIORITY Пріоритет виконуваного потоку може бути змінений в будь-який момент Якщо потоку буде присвоєно пріоритет нижче поточного, то система може запустити інший потік, так як вихідний потік може вже не володіти найвищим пріоритетом Метод getPriority повертає пріоритет потоку

У загальному випадку постійно працююча частина вашої програми повинна мати більш низьким пріоритетом, ніж потік, зайнятий обробкою більш рідкісних подій – наприклад, введення інформації користувачем Скажімо, коли користувач натискає кнопку з написом STOP, він чекає, що додаток негайно зупиниться Якщо оновлення зображення і введення інформації здійснюються з однаковим пріоритетом і під час натискання кнопки відбувається виведення, на те, щоб потік введення зміг зреагувати на натискання кнопки, може знадобитися деякий час Навіть незважаючи на те, що потік виводу має більш низьким пріоритетом, він все одно буде виконуватися більшу частину часу, оскільки потік користувальницького інтерфейсу буде заблокований в очікуванні введення З появою введеної інформації потік користувальницького

інтерфейсу змусить потік виводу зреагувати на запит користувача З цієї причини пріоритет потоку, який повинен виконуватися постійно, встановлюється рівним MIN_PRIORITY, щоб він не поглинав все доступне процесорний час

Кілька методів класу Thread управляють плануванням потоків у системі:

public static void sleep(long millis) throws InterruptedException

Припиняє роботу поточного потоку як мінімум на вказане число мілісекунд Як мінімум означає, що не існує гарантій відновлення роботи потоку точно в зазначений час На час відновлення може вплинути планування потоків у системі, гранулярность і точність системних годин, а також ряд інших факторів

public static void sleep(long millis, int nanos)  throws       InterruptedException

Припиняє роботу поточного потоку як мінімум на вказане число мілісекунд і додаткове число наносекунд Значення інтервалу в наносекундах лежить в діапазоні 0-999999

public static void yield()

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

Наведений нижче приклад демонструє роботу yield Додаток отримує список слів і створює потоки, призначені для виведення окремого слова в списку Перший параметр додатки визначає, повинен Чи кожен потік передавати управління після кожного виклику println значення другого параметра дорівнює кількості повторень слова при виведенні Інші параметри являють собою слова, що входять до списку:

class Babble extends Thread {

static boolean doYield / / Передавати управління іншим потокам Static int howOften / / Кількостей повторів при виведенні

String word / / Слово

Babble(String whatToSay) {

word = whatToSay

}

public void run() {

for (int i = 0 i &lt&lt howOften i++) { Systemoutprintln(word)

if (doYield)

yield () / / Передати управління іншому потоку

}

}

public static void main(String[] args) {

howOften = IntegerparseInt(args[1])

doYield = new Boolean(args[0])booleanValue()

/ / Створити потік для кожного слова і присвоїти йому

/ / Максимальний пріоритет Thread cur = currentThread () cursetPriority (ThreadMAX_PRIORITY) for (int i = 2 i << args.length; i + +)

new babble(args[i])start()

}

}

Коли потоки працюють, не передаючи управління один одному, їм відводяться великі кванти часу – зазвичай цього буває достатньо, щоб закінчити висновок у монопольному режимі Наприклад, при запуску програми з присвоєнням doYield значення false:

Babble false 2 Did DidNot

результат буде виглядати наступним чином: Did

Did

DidNot

DidNot

Якщо ж кожен потік передає управління після чергового println, то інші потоки також отримають можливість працювати Якщо привласнити doYield значення true:

Babble true 2 Did DidNot

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

Did DidNot Did DidNot

Наведені вище результати є приблизними При іншій реалізації потоків вони можуть бути іншими, хоча навіть при однаковій реалізації різні запуски програми можуть дати різні результати Однак при будь реалізації виклик yield підвищує шанси інших потоків у суперечці за процесорний час

Джерело: Арнольд К, Гослінг Д – Мова програмування Java (1997)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*