Пріоритети потоків використовуються планувальником потоків для прийняття рішень про те, коли кожному з потоків буде дозволено працювати. Теоретично високопріоритетні потоки отримують більше часу процесора, ніж фонові. Практично обсяг часу процесора, який отримує потік, часто залежить від декількох факторів крім його пріоритету. (Наприклад, то, як операційна система реалізує багатозадачність, може впливати на відносну доступність часу процесора). Високопріоритетний потік може також вивантажувати фоновий. Наприклад, коли фоновий потік працює, а високопріоритетний збирається продовжити свою перервану роботу (в зв'язку з припиненням або очікуванням завершення операції введення-виведення), то останній вивантажує фоновий потік.
Теоретично потоки з рівним пріоритетом повинні отримувати рівний доступ до центрального процесора. Але ви повинні бути обережні. Пам'ятайте, що Java спроектована для роботи в широкому спектрі середовищ. Деякі з цих середовищ реалізують багатозадачність принципово відмінно від інших. З метою безпеки потоки, які розділяють один і той же пріоритет, повинні отримувати управління в рівній мірі. Це гарантує, що всі потоки отримають можливість виконуватися в середовищі операційних систем з не витісняє багатозадачність. На практиці, навіть у середовищах з не витісняє багатозадачність більшість потоків все-таки мають шанс виконуватися, оскільки більшість потоків неминуче стикаються з блокуючими ситуаціями, такими як очікування введення-виведення. Коли таке трапляється, заблокований потік припиняється, і інші потоки можуть працювати. Але якщо ви хочете домогтися гладкої багатопотокової роботи, то не повинні покладатися на це. До того ж деякі типи завдань інтенсивно навантажують процесор. Такі потоки захоплюють процесор. Потокам такого типу ви повинні передавати управління від випадку до випадку, щоб дати можливість виконуватися іншим.
Щоб встановити пріоритет потоку, використовуйте метод setPriority (), який є членом класу Thread. Так виглядає його загальна форма:
final void setPriority (int рівень)
Тут рівень специфицирует новий рівень пріоритету для викликає потоку. Значення рівень має бути в межах діапазону від MIN_PRIORITY до MAX_PRIORITY. В даний час ці значення рівні відповідно 1 і 10. Щоб повернути потоку пріоритет за замовчуванням, вкажіть NORM_PRlORITY, який в даний час дорівнює 5. Ці пріоритети визначені як статичні фінальні (static final) змінні в класі Thread.
Ви можете отримати поточне значення пріоритету потоку, викликавши метод getPriority () класу Thread, як показано нижче:
final int getPriority ()
У наступному прикладі демонструються два потоки з різними пріоритетами, які виконуються на платформі без витісняє багатозадачності інакше, ніж на платформі зі згаданою многозадачностью. Один потік отримує пріоритет на два рівня вище нормального, як визначено Thread.NORM_PRIORITY, а інший - на два рівня нижче нормального. Потоки стартують і готові до виконання протягом 10 секунд. Кожен потік виконує цикл, що підраховує кількість ітерацій. Через 10 секунд головний потік зупиняє обидва потоку. Потім кількість ітерацій циклу, яке встиг виконати кожен потік, відображається.
// Демонстрація пріоритетів потоків.
class clicker implements Runnable long click = 0;
Thread t;
private volatile boolean running = true;
public clicker (int р) t = new Thread (this);
t.setPriority (p);
>
public void run () while (running) click ++;
>
>
public void stop () running = false;
>
public void start () t. start ();
>
>
class HiLoPri public static void main (String args []) Thread.currentThread ();
setPriority (Thread.MAX_PRIORITY);
clicker hi = new clicker (Thread.NORM_PRIORITY + 2);
clicker lo = new clicker (Thread.NORM_PRIORITY - 2);
lo.start ();
hi.start ();
try Thread.sleep (10000);
>
catch (InterruptedException e) System.out.println ( "Головний потік перерваний.");
>
lo.stop ();
hi.stop ();
// Очікування 10 секунд до переривання.
try hi.t.join ();
lo.t.join ();
>
catch (InterruptedException e) System.out.println ( "перехоплений виняток InterruptedException");
>
System.out.println ( "фонової потік:" + lo.click);
System.out.println ( "високопріоритетних потік:" + hi.click);
>
>
Висновок цієї програми при запуску під Windows показує, що потоки здійснювали перемикання контексту, хоча не було ніякого примусового захоплення процесора і ніяких блокують операцій введення-виведення. Високопріоритетний потік отримав більшу частину часу процесора.
Фоновий потік: 4408112
Високопріоритетний потік: 589626904
Звичайно, точний висновок, що породжується цією програмою, залежить від швидкості вашого процесора і кількості завдань, які виконуються в системі. Коли та сама програма запускається в середовищі з не витісняє багатозадачність, виходить інший результат.
Ще одне зауваження щодо попередньої програми. Зверніть увагу, що змінної running передує слово volatile. Хоча volatile більш докладно пояснюється в главі 13, воно використовується тут, щоб гарантувати, що значення running буде перевірятися на кожному кроці ітерацій циклу:
Без вказівки volatile Java має можливість оптимізувати цикл таким чином, що буде створена локальна копія running. Застосування volatile запобігає цю оптимізацію, повідомляючи Java, що running може змінюватися неявним для коду чином.