multithreading java tutorial with examples
Цей підручник пояснює все про багатопотоковість у Java, реалізацію паралельності, життєвий цикл потоку, приклад класу потоку, нитку з використанням інтерфейсу, що виконується:
Паралельність у комп’ютерному світі - це здатність системи (будь то програма, комп’ютер чи мова програмування) виконувати паралельно кілька екземплярів програми чи програми.
Запускаючи одночасно екземпляри або програми, ми забезпечуємо високу пропускну здатність і вищу продуктивність, оскільки можемо використовувати невикористані ресурси, такі як апаратне забезпечення операційної системи тощо. Наприклад, якщо система має кілька процесорів, то програма може ефективно використовувати ці процесори та збільшити пропускну здатність.
=> Завітайте сюди, щоб ознайомитись із ексклюзивними навчальними посібниками з Java.
Що ви дізнаєтесь:
Що таке багатопоточність у Java
На Java потоки можна розглядати як основу одночасності. Потік - це виконуваний, легкий блок, який отримує доступ до спільних ресурсів, а також до власного стеку викликів.
Додаток Java - це один процес, і в цій програмі ми можемо мати кілька потоків для досягнення паралельності.
Ми знаємо, що програма, що працює в системі, може мати кілька екземплярів, і їх зазвичай називають додатками з багатьма документами. Ці екземпляри додатків називаються процесами. Кожному з цих процесів присвоюється блок виконання, відомий як потік.
Залежно від операційної системи та вимог програми, процесу може бути призначений або один потік, або кілька потоків. Коли процесу застосування присвоюється декілька потоків, тоді нам потрібно виконувати ці кілька потоків одночасно.
' Ця техніка виконання або запуску декількох потоків одночасно або одночасно відома як багатопотоковість . '
Багатопотоковість просто означає, що у нас є більше одного потоку, що виконується всередині однієї програми.
Мова програмування Java має вбудовану підтримку багатопоточності.
Багатопотоковість зображена на наведеній вище схемі. Як показано, є кілька потоків, які працюють одночасно всередині програми.
Наприклад, настільна програма, що забезпечує такі функції, як редагування, друк тощо, є багатопоточною програмою. У цій програмі, оскільки друк є фоновим процесом, ми можемо виконувати редагування документів та друк документів одночасно, призначаючи ці функції двом різним потокам.
Потоки в багатопотокових програмах паралельно виконуються паралельно один одному. Таким чином, багатопотоковість також є частиною одночасності в Java. Зверніть увагу, що, хоча існує кілька потоків, вони ділять область пам'яті, тим самим заощаджуючи пам'ять. Крім того, потоки можуть швидко переключити контекст в найкоротші терміни.
Багатопотоковість переважно корисна, оскільки забезпечує одночасне виконання двох або більше частин програми. Це дозволяє додатку максимально використовувати час процесора, а час простою зводиться до мінімуму.
Нижче наведено деякі терміни, які ми повинні знати стосовно багатопотокового середовища, оскільки вони часто використовуються.
Багатозадачність: У багатозадачності одночасно виконується більше одного завдання.
Багатопотоковість: Багатопотоковість, як уже зазначалося, є процесом виконання декількох потоків одночасно.
різниця між навантаженням і тестуванням продуктивності
Багатопроцесорна обробка: При багатопроцесорній обробці виконується одночасно більше одного процесу. Подібно до багатозадачності, але тут задіяно більше одного процесора.
Паралельна обробка: Паралельна обробка - це техніка, коли в комп'ютерній системі одночасно працюють декілька процесорів.
Обговоривши багатопотоковість, виникає питання, чому нам взагалі потрібна багатопотоковість?
Переваги багатопоточності
Багатопотоковість має різні переваги, які сприяють ефективному програмуванню.
Наведені нижче пункти дадуть зрозуміти.
# 1) Ефективне використання єдиних систем ЦП
Коли в системі є лише один процесор, з одним потоком, час процесора витрачається даремно. Коли потік зайнятий використанням інших ресурсів, таких як IO, центральний процесор не працює. Ми можемо вдосконалити це і краще використовувати центральний процесор, маючи багатопотокові програми.
Використовуючи багатопотоковість, якщо один потік виконується з центральним процесором, тоді інший потік може його використовувати. З кількома потоками час простою процесора значно зменшиться.
# 2) Ефективне використання декількох системних процесорів
Подібно до одинарних центральних процесорів, навіть із системами, що мають кілька центральних процесорів, багатопотокові програми можуть ефективно використовувати кілька центральних процесорів.
# 3) Покращений досвід користування щодо чуйності та справедливості
Швидкість реагування системи покращується завдяки багатопоточним додаткам. Ми не відчуваємо цього „Графічний інтерфейс“ коли у нас є кілька потоків, що виконують різні завдання в додатку, і користувачам не потрібно довго чекати, щоб отримати відповідь на свої запити.
Подібним чином користувачі належним чином обслуговують багатопотокові системи.
Як реалізувати паралельність у Java
Першим класом, за допомогою якого ми можемо реалізувати паралельність у Java, є java.lang.Thread клас. Цей клас Thread формує основу одночасності в Java.
У нас теж є java.lang.Виконуваний інтерфейс, який може бути реалізований класом Java для абстрагування поведінки потоку. Для розширеної розробки додатків ми можемо використовувати java.util.concurrent пакет, доступний з Java 1.5.
Просуваючись далі, ми детально обговоримо паралельність у Java. Давайте обговоримо та зрозуміємо поняття потоків у Java у цьому підручнику. У наступних підручниках з багатопоточності ми розглянемо різні концепції багатопоточності та паралельності.
Що таке нитка в Java
Одну нитку можна визначити як найменшу та найлегшу одиницю обробки. На Java потоки використовуються в програмах, що використовують клас «Thread».
Потоки Java бувають двох типів:
# 1) Потік користувача: Потік користувача створюється при першому запуску програми. Тоді ми можемо створити якомога більше потоків користувачів та демонів.
# 2) Потік демона: нитки демона в основному використовуються у фоновому режимі і використовуються для таких завдань, як очищення програми тощо.
Потоки знижують вартість обслуговування додатка. Це також зменшує накладні витрати на програму.
Нижче наведено приклад одного потоку:
public class Main{ public static void main (String () args){ System.out.println('This is a thread'); } }
У наведеній вище програмі відображатиметься 'Це нитка', оскільки при запуску програми створюється потік користувача. У наведеній вище програмі основною функцією є початкова точка програми і вона створює потік користувача.
Життєвий цикл нитки
На наступній схемі зображено життєвий цикл потоку в Java.
Як показано на наведеній вище схемі, потік у Java має такі стани:
# 1) Нове: Спочатку потік, щойно створений із класу потоків, має 'новий' стан. Це ще не розпочато. Ця нитка також називається «Народжена нитка» .
# 2) Можна виконувати: У цьому стані екземпляр потоку викликається за допомогою методу «Почати» .
# 3) Біг: Викликається метод запуску екземпляра потоку, і потік починає виконання. Це запущений стан. В основному планувальник планує та керує потоками.
# 4) Заблоковано: У додатку є кілька потоків. Ці потоки повинні чекати іншого, оскільки їх виконання повинно бути синхронізовано.
# 5) Припинено: Після закінчення процесу виконання потоку завершується потік або зупиняється його виконання.
Отже, спочатку створюється потік, потім планується, а пізніше планувальник виконує потік. У той час як запущений потік може бути заблокований або призупинений для якоїсь іншої діяльності. Потім він відновлюється, і по завершенні обробки потік виконується.
гнучкі запитання та відповіді для досвідчених
Пріоритети ниток
Пріоритет потоку вирішує, як слід обробляти один потік щодо інших потоків у програмі. Пріоритет потоку - це ціле число.
Нижче наведено кілька моментів, які слід пам’ятати щодо пріоритетів ниток:
- Пріоритетами нитки є цілі числа.
- Використовуючи пріоритет потоку, ми можемо вирішити, коли нам слід перейти з одного потоку в робочому стані на інший. Це процес перемикання контексту, в якому ми перемикаємо контексти потоків.
- У будь-який час потік може добровільно звільнити свій контроль над процесором. Тоді нитка з найвищим пріоритетом може взяти на себе.
- Подібним чином, потік з вищим пріоритетом може випереджати будь-який інший потік з нижчим пріоритетом.
- Клас Thread забезпечує метод setPriority (), який використовується для встановлення пріоритету потоку.
- Ми також можемо використовувати константи MIN_PRIORITY, MAX_PRIORITY або NORM_PRIORITY замість цілих чисел.
Створити нитку
Ми можемо створити нитку, використовуючи один із наведених нижче способів:
- Розширення класу Java «Thread».
- Реалізація «Runnable».
Розширення класу Java «Thread»
Клас 'Thread' містить конструктори та методи, які дозволяють нам створювати та виконувати операції над об'єктом потоку. Клас Thread внутрішньо реалізує інтерфейс Runnable, а також розширює клас Object.
У наступній таблиці наведено короткий опис різних конструкторів та методів класу Thread ().
Будівельник / | Прототип | Опис |
---|---|---|
спати | публічний порожній сон (довгі мілісекунди) | Виконання поточного потоку зупиняється на вказані мілісекунди. |
Конструктор потоку () | Потік () | Конструктор за замовчуванням для створення об’єкта Thread. |
Потік (ім'я рядка) | Конструктор для створення об'єкта Thread із зазначеним ім'ям. | |
Різьба (що працює) | Створіть екземпляр Thread із зазначеним об’єктом інтерфейсу, що виконується. | |
Потік (Runnable r, ім'я рядка) | Створіть екземпляр Thread із вказаним об’єктом інтерфейсу, який можна запустити, та заданим ім’ям | |
бігти | public void run () | Метод запуску виконує дію для потоку. Викликає нитку. |
почати | публічний старт недійсним () | Використовується для початку виконання потоку. Внутрішньо JVM викликає метод run () у цьому потоці. |
приєднуватися | public void join () | Зачекайте, поки нитка загине |
публічне приєднання порожнечі (довгі мілісекунди) | Зачекайте вказані мілісекунди, поки нитка помре. | |
getPriority | public int getPriority () | Повернути пріоритет потоку |
setPriority | public int setPriority (пріоритет int) | Змініть пріоритет потоку на вказаний пріоритет |
getName | public String getName () | повернути ім'я потоку. |
setName | public void setName (ім'я рядка) | Встановіть для імені потоку вказаний рядок |
currentThread | public Thread currentThread () | Повертає посилання на нитку, яка активна в даний момент |
getId | public int getId () | Повернути ідентифікатор потоку |
getState () | public Thread.State getState () | Повертає поточний стан потоку |
живий | загальнодоступний логічний isAlive () | Перевірте, чи потік живий, і поверніть true, якщо так. |
врожайність | прибутковість публічної порожнечі () | Тимчасово призупиняє поточний потік і дозволяє виконувати інші потоки. |
isDeemon | загальнодоступний логічний isDaemon () | Перевірте, чи є нитка демоновою; повернути true, якщо так. |
setDaemon | public void setDaemon (логічне значення b) | Встановити потік як демон-потік, якщо b = істина; ще встановлено як потік користувача. |
перебивати | public void interrupt () | Перервати поточний потік. |
isInterrupted | загальнодоступне логічне значення isInterrupted () | Перевірте, чи нитка не перервана. |
перерваний | загальнодоступний статичний булевий перерваний () | Перевірте, чи поточний потік не перервано. |
dumpStack | Статичний порожній dumpStack () | Друкує трасування потоку поточного потоку до стандартного потоку помилок. |
призупинити | public void suspend () | Призупиняє всі нитки. (** метод застарілий у останніх версіях Java) |
резюме | публічне порожнече резюме () | Відновити підвішену нитку. (** метод застарілий у останніх версіях Java) |
Стоп | зупинка публічної порожнечі () | Зупиняє нитку. (** метод застарілий у останніх версіях Java) |
Ми розглянемо ці методи потоків у нашому наступному підручнику з багатопоточності.
Запуск нитки
Метод start (), який використовується для запуску потоку, виконує наступні кроки:
- Запускає новий екземпляр потоку з новим CallStack.
- Стан потоку змінено з нового на запущений.
- Коли настає черга потоку, він виконує метод run ().
Реалізація інтерфейсу, що працює
Екземпляр потоку також можна створити за допомогою інтерфейсу Runnable. Для створення екземпляра потоку клас, об'єкти якого повинні виконуватися потоком, повинен реалізувати інтерфейс Runnable.
Інтерфейс Runnable має лише один метод:
public void run () => this method is used to execute the thread.
Приклад класу ниток
Тепер продемонструємо потік на Java за допомогою класу потоків.
//class inherited from 'Thread' class ThreadClassDemo extends Thread { private int number; //class constructor public ThreadClassDemo(int number) { this.number = number; } //run method => execution code for thread public void run() { int counter = 0; int numInt = 0; //prints the number till specified number is reached, starting from 10 do { numInt = (int) (counter + 10); System.out.println(this.getName() + ' prints ' + numInt); counter++; } while(numInt != number); System.out.println('** Correct! ' + this.getName() + 'printed ' + counter + ' times.**'); } } public class Main { public static void main(String () args) { System.out.println('Starting thread_1...'); //create a thread class instance Thread thread_1 = new ThreadClassDemo(15); //start the thread thread_1 thread_1.start(); try { //wait for thread_1 to die thread_1.join(); } catch (InterruptedException e) { System.out.println('Thread interrupted.'); } System.out.println('Starting thread_2...'); Thread thread_2 = new ThreadClassDemo(20); //start thread_2 thread_2.start(); System.out.println('main() is ending...'); } }
Вихідні дані
Потік Java за допомогою запущеного інтерфейсу
Наступний приклад демонструє використання інтерфейсу Runnable для створення екземпляра потоку.
//class implements Runnable interface class RunnableDemo implements Runnable { private String message; //class constructor public RunnableDemo(String message) { this.message = message; } //run method public void run() { while(true) { System.out.println(message); } } } public class Main { public static void main(String () args) { //create first thread instance hello Runnable hello = new RunnableDemo('Hello, Greetings!!!'); Thread thread1 = new Thread(hello); thread1.setDaemon(true); //set this thread as daemon thread1.setName('hello'); System.out.println('Starting First thread...'); //start the thread thread1.start(); //create second thread instance bye Runnable bye = new RunnableDemo('Bye for now!!'); Thread thread2 = new Thread(bye); thread2.setPriority(Thread.MIN_PRIORITY); //set priority to min thread2.setDaemon(true); //set as daemon thread System.out.println('Starting goodbye thread...'); //start the thread thread2.start(); System.out.println('main() is ending...'); } }
Вихідні дані
Як зупинити нитку в Java
Ми бачили приклади ниток вище. З цих прикладів ми знаємо, що коли метод run завершує виконання, потік зупиняється або він також зупиняється через деякі винятки.
У попередніх версіях Java був метод stop () у класі Thread, який можна було використовувати для безпосередньої зупинки потоку. Але зараз він застарів із міркувань безпеки. Таким чином, нам потрібно використовувати інші методи, щоб зупинити потік, який виконується.
Існує два методи, які ми можемо застосувати, щоб зупинити нитку.
- Використання летючої булевої змінної
- Використання переривань.
У цьому розділі ми обговоримо обидва ці методи зупинки потоку.
Використання летючої булевої змінної
У цьому методі ми підтримуємо логічну змінну say flag, щоб зупинити потік. Потік працює, доки для логічної змінної встановлено значення true. У той момент, коли воно стає хибним, потік зупиняється.
Особливістю цього методу є те, що ми оголошуємо логічну змінну як “ мінливий ”, Щоб він завжди зчитувався з основної пам'яті, а програма не могла кешувати його в кеші процесора. Таким чином, не буде ніякої різниці в значеннях, встановлених і прочитаних.
Здійснення зупинки потоку за допомогою летючої булевої змінної показано нижче.
class StopThread extends Thread { private volatile boolean stop_flag = true; //initially set to true public void stopRunning() { stop_flag = false; //set stop_flag to false } @Override public void run() { while (stop_flag) { //keep checking value of stop_flag System.out.println('Thread is running...'); } System.out.println('Thread stopped!!!'); } } public class Main { public static void main(String() args) { //create a thread instance StopThread stop_thread = new StopThread(); //start the thread stop_thread.start(); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //call stopRunning() method to stop the thread stop_thread.stopRunning(); } }
Вихідні дані
Примітка: Тут ми показали лише частину результату. Потік може працювати кілька хвилин перед зупинкою. Так що ми можемо отримувати різні результати на різних системах.
Використання переривань
Тут потік зупиняється за допомогою методу interrupt (), як ми вже обговорювали вище в методах класу потоків. Метод interrupt () встановлює статус потоку як перерваний. Цей статус передається циклу while методу run (). Ми можемо отримати статус перерваного, використовуючи метод interrupted ().
Наступна програма демонструє використання методу interrupt () для зупинки потоку.
class StopThread extends Thread { @Override public void run() { while (!Thread.interrupted()) { //check for interrupted status System.out.println('Thread is running...'); } System.out.println('Thread stopped!!!'); } } public class Main { public static void main(String() args) { //create a thread instance StopThread stop_thread = new StopThread(); //start the thread stop_thread.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //interrupt the thread stop_thread.interrupt(); } }
Вихідні дані
Часті запитання
Q # 1) Чому ми використовуємо багатопоточність у Java?
Відповідь: Багатопотоковість дозволяє одночасне або одночасне виконання двох або більше потоків у програмі. Одночасне виконання максимізує пропускну здатність, а також використовує центральний процесор до максимуму.
Q # 2) Що таке багатопоточність? Які її типи?
Відповідь: Багатопотоковість означає виконання декількох потоків. Це виконання може бути одночасним або паралельним. Таким чином, багатопотоковість має два типи, тобто паралельний або паралельний.
Запитання №3) Що таке багатопоточність проти багатопроцесорної обробки?
Відповідь: У багатопотоковості існує кілька потоків для одного і того ж або різних процесів, і ці потоки виконуються одночасно, щоб підвищити обчислювальну швидкість системи. При багатопроцесорній обробці система має більше двох центральних процесорів і кілька процесів виконуються одночасно.
Q # 4) Які переваги багатопоточності в Java?
Відповідь: За допомогою багатопоточності ми можемо виконувати різні частини програми одночасно за допомогою потоків. Багатопотоковість збільшує пропускну здатність системи. Багатопотоковість також максимізує використання ЦП, оскільки різні потоки постійно використовують ЦП.
Q # 5) Чи багатопоточність хороша для ігор?
Відповідь: Так, особливо для сучасних ігор.
Висновок
Це все про впровадження багатопоточності. У цьому підручнику ми обговорювали паралельність та багатопоточність у Java. Ми обговорили створення потоку з класом Thread, а також інтерфейсом Runnable і навели відповідні приклади.
Ми також детально вивчили поняття єдиної нитки та її створення. Концепції ниток, включаючи життєвий цикл нитки, зупинку нитки, типи ниток тощо, обговорювались у цьому посібнику.
Ми також обговорили багатопотоковість і довжину та паралельність у Java. Наприкінці цього підручника читач повинен мати можливість легко зрозуміти поняття паралельності та багатопоточності, а також потоки в Java.
=> Зверніть увагу на прості навчальні серії Java тут.
Рекомендована література
- Багатопотоковість на C ++ з прикладами
- Потоки Java з методами та життєвим циклом
- Thread.Sleep () - метод Thread Sleep () у Java із прикладами
- Підручник JAVA для початківців: 100+ практичних навчальних посібників Java
- Підручник з роздумів про Java з прикладами
- Рядок Java містить () Підручник із методів із прикладами
- Нерівний масив у Java - Підручник із прикладами
- Підручник з класу сканера Java із прикладами