Вступ
Перш ніж дізнатися про потоки Java, давайте заглянемо в недалеке майбутнє. Уявіть, що ви подали резюме та пройшли співбесіду. Вас та пару дюжин майбутніх колег запитабо на роботу у велику Software-компанію. Серед інших клопотів потрібно подати паперові документи для працевлаштування співробітнику HR-відділу, що втомився.
Щоб прискорити процес, претендентів на посаду можна поділити на дві групи та розподілити їх між двома HR-менеджерами (якщо такі є у компанії). В результаті ми отримуємо прискорення процесу за рахунок паралельної (
parallel ) роботи з оформлення.
Якщо ж кадровик у компанії один, то доведеться якось викручуватися. Наприклад, можна знову розбити всіх на дві групи, наприклад, співбесідувати по черзі дівчат і юнаків.
Або за іншим принципом: так як у нижній групі більше народу, чергуватимемо на одного юнака двох дівчат.
Такий спосіб організації роботи називається
багатопоточним . Наша стомлена кадровик переключається на різні групи для оформлення з них чергового співробітника. Груп, можливо, одинадцять, а кадровиків – чотири. У цьому випадку багатопотокова (
multithreading ) обробка буде відбуватися паралельно кількома HR-ами, які можуть брати чергову людину з будь-якої групи для обробки її документів.
Процеси
Процесом (
process ) у разі буде організація роботи прийому документів. В організації можна виділити кілька процесів: бухгалтерський облік, розробка програмного забезпечення, зустрічі з клієнтами, робота складу і т. д. На кожен процес виділені ресурси: приміщення, співробітники для його виконання. Процеси ізольовані один від одного: у кадровиків відсутній доступ до бухгалтерської бази, а менеджери по роботі з клієнтами не бігають по складу. Якщо процес має отримати доступ до чужих ресурсів, необхідно налагодити міжпроцесну взаємодію: службові записки, спільні наради.
Потоки
Робота у процесі організована як потоків (
java thread
). Для відділу кадрів потік – це організація роботи з обслуговування групи. На першій картинці – один потік, наступних трьох – два. Усередині процесу потоки можуть виконуватися паралельно – два кадровики приймають дві чи більше групи майбутніх співробітників. Взаємодія кадровиків із групами – обробку потоків усередині процесу – називають
синхронізацією потоків. На малюнках оформлення одним кадровиком двох груп видно показані методи: рівномірний (дівчина – юнак – дівчина – юнак) і з різними пріоритетами (дві дівчини чергуються з одним юнаком). Потоки мають доступ до ресурсів процесу, до якого вони належать: груп до кадровика дано зразки бланків заяв, ручки для заповнення документів. Але якщо потоки взаємодіють із спільними для них речами – то можливі казуси. Якщо кадровик попросить крикнути ім'я останньої людини у черзі – то, у випадку із двома групами, він не впевнений заздалегідь, що почує жіноче чи чоловіче ім'я. Подібні конфлікти доступу до даних, блокування та способи їх вирішення є дуже важливою темою.
Стан потоку
Кожен потік перебуває в одному з наступних станів:
- Створено (
New
) – черга до кадровика готується, люди організовуються.
- Запущено (
Runnable
) – наша черга вишикувалася до кадровика та обробляється.
- Заблокований (
Blocked
) – останній у черзі юнак намагається вигукнути ім'я, але почувши, що дівчина у сусідній групі почала робити це раніше за нього, замовк.
- Завершено (
Terminated
) — вся черга оформилася у кадровика і не потребує.
- Чекає(
Waiting
) – одна черга чекає сигналу з іншого.
Організація потоків та його взаємодія – це основа ефективної роботи процесів.
Повернемося до IT-світу
У XXI столітті багатопоточне та паралельне виконання стало актуальним. З 90-х років минулого століття багатозадачні операційні системи Windows, MacOS та Linux міцно влаштувалися на домашніх комп'ютерах. Вони часто можна зустріти чотири- і більше ядерні процесори. Число паралельних блоків GPU-відеокарту вже перевалило за тисячу. Популярні програми пишуться з урахуванням багатопоточності (multithreading), наприклад, сучасні версії програмного забезпечення обробки графіки, відео або оперують великим обсягом даних: Adobe Photoshop, WinRar, Mathematica, сучасні ігри. Багатопотоковість Java - дуже важлива, затребувана і складна тема. Тому в курсі JavaRush зустрічається багато завдань, щоб розібратися з нею дуже добре. Java-приклади на багатопоточність допоможуть освоїти основні нюанси та тонкощі цієї галузі, синхронізацію роботи потоків.
Процес
Process (процес) – екземпляр програми, що виконується, якому Операційна Система (ОС) виділила пам'ять, процесорний час/ядра та інші ресурси. Важливо, що пам'ять виділяється окремо, адресані простори різних процесів недоступні одне одному. Якщо процесам необхідно обмінюватися даними, можуть це зробити з допомогою файлів, каналів та інших методів межпроцессного взаємодії.
Потік
Java
Thread
(потік). Іноді, щоб не плутати з іншими класами Java -
Stream
і подібними, потоки Java часто переводять як нитку. Вони використовують виділені для процесу ресурси та є способом виконання процесу. Головний потік виконує метод
main
та завершується. При виконанні процесу можуть бути додаткові потоки (дочірні). Потоки одного процесу можуть обмінюватися даними між собою. Багатопотоковість Java вимагає враховувати синхронізацію даних, не забувайте про це. У Java процес завершується тоді, коли закінчив роботу останній його потік. Для фонових завдань потік можна запустити як демон (
daemon
), відмінність якого від звичайного в тому, що вони будуть примусово завершені після закінчення роботи всіх потоків
daemon
процесу.
Перший багатопотоковий додаток
Існує більш ніж півдюжини способів створення потоків, в рамках JavaRush курсу ми їх докладно розберемо. Для початку познайомимося з одним із базових. Є спеціальний клас
Thread
у методі
run()
якого необхідно написати код, що реалізує логіку програми. Після створення потоку можна запустити його, викликавши метод
start()
. Напишемо демонстраційну програму, що реалізує приклад багатопоточності Java.
class PeopleQueue extends Thread {
private String[] names;
PeopleQueue(String... names) {
this.names = names;
}
@Override
public void run() {
for (int i = 0; i < names.length; i++) {
System.out.println("Обработаны документы: " + names[i]);
try {
sleep(500);
} catch (Exception e) {}
}
}
}
public class HR {
public static void main(String[] args) {
PeopleQueue queue1 = new PeopleQueue("Іван","Сергей","Николай","Фердинанд","Василь");
PeopleQueue queue2 = new PeopleQueue("Мария","Людмила","Алиса","Карина","Ольга");
System.out.println("Начали!");
queue1.start();
queue2.start();
}
}
Запустимо програму. У консолі видно виведення повідомлення основним потоком. Далі кожен дочірній потік
queue1
і
queue2
по черзі виводять повідомлення в загальну для них консоль про чергового обробленого співробітника. Один із можливих варіантів роботи програми:
Начали!
Обработаны документы: Мария
Обработаны документы: Іван
Обработаны документы: Людмила
Обработаны документы: Сергей
Обработаны документы: Алиса
Обработаны документы: Николай
Обработаны документы: Карина
Обработаны документы: Фердинанд
Обработаны документы: Ольга
Обработаны документы: Васабой
Process finished with exit code 0
Багатопотоковість в Java - тема важка і багатостороння. Вміння писати код з використанням паралельних, багатозадачних та багатопотокових обчислень допоможе вам ефективно реалізувати завдання на сучасних багатоядерних процесорах та кластерах, що складаються з безлічі комп'ютерів.