Урок за многопоточност в Java с примери

Съдържание:

Anonim

Всяко приложение може да има множество процеси (екземпляри). Всеки от този процес може да бъде присвоен или като единична нишка, или като множество нишки. В този урок ще видим как да изпълняваме множество задачи едновременно и също така ще научим повече за нишките и синхронизирането между нишките.

В този урок ще научим:

  • Какво е единична нишка
  • Какво е Multithreading в Java?
  • Жизнен цикъл на нишката в Java
  • Синхронизация на нишки Java
  • Пример за многопоточност на Java

Какво е единична нишка?

Една нишка е основно лека и най-малката единица за обработка. Java използва нишки, като използва "Thread Class".

Има два вида нишки - потребителска нишка и демонова нишка (демонови нишки се използват, когато искаме да почистим приложението и се използват във фонов режим).

Когато приложението започне за първи път, се създава потребителска нишка. Публикувайте това, можем да създадем много потребителски нишки и демонови нишки.

Пример за единична нишка:

демотест на пакета;публична класа GuruThread{публична статична void main (String [] args) {System.out.println ("Една нишка");}}

Предимства на една нишка:

  • Намалява режийните разходи в приложението при изпълнение на единична нишка в системата
  • Освен това намалява разходите за поддръжка на приложението.

Какво е Multithreading в Java?

MULTITHREADING в Java е процес на изпълнение на две или повече нишки едновременно до максимално използване на процесора. Многонишковите приложения изпълняват едновременно две или повече нишки. Следователно той е известен също като Concurrency в Java. Всяка нишка върви успоредно една на друга. Многобройните нишки не отделят отделна област на паметта, следователно те спестяват памет. Освен това превключването на контекста между нишките отнема по-малко време.

Пример за многонишка

демотест на пакета;публичен клас GuruThread1 изпълнява Runnable{публична статична void main (String [] args) {Thread guruThread1 = нова нишка ("Guru1");Thread guruThread2 = нова нишка ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("Имената на нишките са следните:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@Overridepublic void run () {}}

Предимства на многонишковото:

  • Потребителите не са блокирани, тъй като нишките са независими и можем да изпълняваме множество операции наведнъж
  • Като такива нишките са независими, останалите нишки няма да бъдат засегнати, ако една нишка отговаря на изключение.

Жизнен цикъл на нишката в Java

Жизненият цикъл на една нишка:

Има различни етапи от жизнения цикъл на резбата, както е показано на горната диаграма:

  1. Ново
  2. Изпълним
  3. Бягане
  4. Очакване
  5. Мъртъв
  1. Ново: В тази фаза нишката се създава с помощта на клас "Thread class". Тя остава в това състояние, докато програмата стартира нишката. Известен е още като родена нишка.
  2. Изпълним: На тази страница екземплярът на нишката се извиква с начален метод. Контролът на нишката се дава на планировчика, за да завърши изпълнението. Зависи от програмиста дали да стартирате нишката.
  3. Изпълнява се: Когато нишката започне да се изпълнява, тогава състоянието се променя на "работещо" състояние. Планировчикът избира една нишка от пула нишки и тя започва да се изпълнява в приложението.
  4. Изчакване: Това е състоянието, когато нишката трябва да изчака. Тъй като в приложението се изпълняват множество нишки, има нужда от синхронизация между нишките. Следователно една нишка трябва да изчака, докато другата нишка бъде изпълнена. Следователно това състояние се нарича състояние на изчакване.
  5. Dead: Това е състоянието, когато нишката е прекратена. Нишката е в работещо състояние и веднага след като завърши обработката, тя е в „мъртво състояние“.

Някои от често използваните методи за нишки са:

Метод Описание
старт () Този метод стартира изпълнението на нишката и JVM извиква метода run () за нишката.
Сън (int милисекунди) Този метод прави нишката спяща, следователно изпълнението на нишката ще бъде на пауза за предоставени милисекунди и след това нишката отново започва да се изпълнява. Това помага при синхронизирането на нишките.
getName () Той връща името на нишката.
setPriority (int newpriority) Променя приоритета на нишката.
добив () Това води до изпълнение на текущата нишка при спиране и други нишки.

Пример: В този пример ще създадем нишка и ще изследваме вградените методи, достъпни за нишки.

демотест на пакета;публичен клас thread_example1 реализира Runnable {@Overridepublic void run () {}публична статична void main (String [] args) {Тема guruthread1 = нова нишка ();guruthread1.start ();опитвам {guruthread1.sleep (1000);} catch (InterruptedException e) {// TODO Автоматично генериран блок за уловe.printStackTrace ();}guruthread1.setPriority (1);int gurupriority = guruthread1.getPriority ();System.out.println (gurupriority);System.out.println („Темата се изпълнява“);}}

Обяснение на кода:

  • Кодов ред 2: Създаваме клас "thread_Example1", който реализира интерфейса Runnable (той трябва да бъде реализиран от всеки клас, чиито екземпляри са предназначени да бъдат изпълнени от нишката.)
  • Код ред 4: Той отменя метода на изпълнение на интерфейса за изпълнение, тъй като е задължително да се замени този метод
  • Кодов ред 6: Тук дефинирахме основния метод, при който ще започнем изпълнението на нишката.
  • Кодов ред 7: Тук създаваме ново име на нишка като "guruthread1" чрез създаване на инстанция на нов клас нишка.
  • Кодов ред 8: ще използваме метода "старт" на нишката, като използваме екземпляр "guruthread1". Тук нишката ще започне да се изпълнява.
  • Кодов ред 10: Тук използваме метода "спящ" на нишката, като използваме екземпляр "guruthread1". Следователно нишката ще спи за 1000 милисекунди.
  • Код 9-14: Тук сме поставили метода за заспиване в блока try catch, тъй като има проверено изключение, което се появява, т.е.
  • Кодов ред 15: Тук задаваме приоритета на нишката на 1 от който и приоритет да е бил
  • Код ред 16: Тук получаваме приоритета на нишката с помощта на getPriority ()
  • Кодов ред 17: Тук отпечатваме стойността, извлечена от getPriority
  • Кодов ред 18: Тук пишем текст, който нишката работи.

Когато изпълните горния код, получавате следния изход:

Изход:

5 е приоритетът на Thread, а Thread Running е текстът, който е изходът на нашия код.

Синхронизация на нишки Java

При многопоточност има асинхронно поведение на програмите. Ако една нишка пише някои данни, а друга нишка, която чете данни едновременно, може да създаде несъответствие в приложението.

Когато има нужда от достъп до споделените ресурси от две или повече нишки, тогава се използва подход за синхронизация.

Java е предоставила синхронизирани методи за внедряване на синхронизирано поведение.

При този подход, след като нишката достигне вътре в синхронизирания блок, тогава никоя друга нишка не може да извика този метод за същия обект. Всички нишки трябва да изчакат, докато тази нишка завърши синхронизирания блок и излезе от него.

По този начин синхронизацията помага в многонишко приложение. Едната нишка трябва да изчака, докато друга нишка завърши изпълнението си, само тогава останалите нишки са разрешени за изпълнение.

Може да се напише в следната форма:

Синхронизирано (обект){// Блок от оператори, които трябва да се синхронизират}

Пример за многопоточност на Java

В този пример ще вземем две нишки и ще извлечем имената на нишката.

Пример1:

GuruThread1.javaдемотест на пакета;публичен клас GuruThread1 изпълнява Runnable {/ *** @param аргументи* /публична статична void main (String [] args) {Thread guruThread1 = нова нишка ("Guru1");Thread guruThread2 = нова нишка ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("Имената на нишките са следните:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@Overridepublic void run () {}}

Обяснение на кода:

  • Кодов ред 3: Взехме клас "GuruThread1", който реализира Runnable (той трябва да бъде реализиран от всеки клас, чиито екземпляри са предназначени да бъдат изпълнени от нишката.)
  • Кодова линия 8: Това е основният метод на класа
  • Кодов ред 9: Тук създаваме инстанция на класа Thread и създаваме екземпляр, наречен „guruThread1“ и създаваме нишка.
  • Кодов ред 10: Тук създаваме инстанция на класа Thread и създаваме екземпляр с име „guruThread2“ и създаваме нишка.
  • Кодов ред 11: Стартираме нишката, т.е. guruThread1.
  • Кодов ред 12: Стартираме нишката, т.е. guruThread2.
  • Кодов ред 13: Извеждане на текста като "Имената на нишките са следните:"
  • Кодов ред 14: Получаване на името на нишка 1 с помощта на метода getName () на нишковия клас.
  • Код ред 15: Получаване на името на нишка 2 с помощта на метода getName () на нишката клас.

Когато изпълните горния код, получавате следния изход:

Изход:

Имената на нишките се извеждат тук като

  • Гуру1
  • Гуру2

Пример 2:

В този пример ще научим за заместващите методи run () и start () на изпълним интерфейс и ще създадем две нишки от този клас и ще ги стартираме съответно.

Също така, ние вземаме два класа,

  • Такъв, който ще изпълни управляемия интерфейс и
  • Друг, който ще има основния метод и ще изпълни съответно.
демотест на пакета;публична класа GuruThread2 {публична статична void main (String [] args) {// TODO Автоматично генериран мъниче от методGuruThread3 threadguru1 = нов GuruThread3 ("guru1");threadguru1.start ();GuruThread3 threadguru2 = нов GuruThread3 ("guru2");threadguru2.start ();}}клас GuruThread3 изпълнява Runnable {Тема guruthread;частно низово гурунаме;GuruThread3 (име на низ) {guruname = име;}@Overridepublic void run () {System.out.println ("Темата работи" + guruname);за (int i = 0; i <4; i ++) {System.out.println (i);System.out.println (guruname);опитвам {Thread.sleep (1000);} catch (InterruptedException e) {System.out.println („Нишката е прекъсната“);}}}обществен празен старт () {System.out.println („Нишката е стартирана“);if (guruthread == null) {guruthread = нова нишка (това, guruname);guruthread.start ();}}}

Обяснение на кода:

  • Код ред 2: Тук ще вземем клас "GuruThread2", който ще има основния метод в него.
  • Код ред 4: Тук ще вземем основен метод от класа.
  • Кодов ред 6-7: Тук създаваме екземпляр на клас GuruThread3 (който е създаден в долните редове на кода) като „threadguru1“ и започваме нишката.
  • Код ред 8-9: Тук създаваме друг екземпляр на клас GuruThread3 (който е създаден в долните редове на кода) като "threadguru2" и започваме нишката.
  • Кодов ред 11: Тук създаваме клас "GuruThread3", който изпълнява изпълним интерфейс (той трябва да бъде реализиран от всеки клас, чиито екземпляри са предназначени да бъдат изпълнени от нишката.)
  • Кодова линия 13-14: вземаме две променливи на класа, от които едната е от типа нишка, а другата от низовия клас.
  • Кодов ред 15-18: ние отменяме конструктора GuruThread3, който приема един аргумент като тип низ (който е име на нишки), който се присвоява на променлива на класа guruname и следователно името на нишката се съхранява.
  • Кодова линия 20: Тук ние заместваме метода run () на интерфейса за изпълнение.
  • Кодов ред 21: Извеждаме името на нишката с помощта на оператора println.
  • Кодов ред 22-31: Тук използваме цикъл for с брояч, инициализиран на 0, и той не трябва да бъде по-малък от 4 (можем да вземем всяко число, следователно цикълът ще работи 4 пъти) и увеличаване на брояча. Ние отпечатваме името на нишката и също така правим нишката да спи в продължение на 1000 милисекунди в рамките на блок за опит за улавяне, тъй като методът на заспиване е поставил отметка за изключение.
  • Код ред 33: Тук ние заместваме метода за стартиране на управляемия интерфейс.
  • Кодов ред 35: Извеждаме текста "Thread started".
  • Кодов ред 36-40: Тук приемаме условие if, за да проверим дали променливата на класа guruthread има стойност в него или не. Ако е нула, тогава създаваме екземпляр, използвайки клас на нишка, който приема името като параметър (стойност, за която е присвоена в конструктора). След което нишката се стартира чрез метода start ().

Когато изпълнявате горния код, получавате следния изход:

Изход :

Следователно има две нишки, ние два пъти получаваме съобщение „Нишката е стартирана“.

Получаваме имената на нишката, както сме ги извели.

Той влиза в цикъл for, където отпечатваме брояча и името на нишката и броячът започва с 0.

Цикълът се изпълнява три пъти и между нишката се преспива за 1000 милисекунди.

Следователно първо получаваме guru1, след това guru2, след това отново guru2, защото нишката спи тук за 1000 милисекунди и след това следващия guru1 и отново guru1, нишката спи за 1000 милисекунди, така че получаваме guru2 и след това guru1.

Резюме :

В този урок видяхме многонишкови приложения в Java и как да използваме единични и много нишки.

  • При многопоточност потребителите не са блокирани, тъй като нишките са независими и могат да извършват множество операции едновременно
  • Различни етапи от жизнения цикъл на конеца са,
    • Ново
    • Изпълним
    • Бягане
    • Очакване
    • Мъртъв
  • Научихме и за синхронизацията между нишките, които помагат на приложението да работи безпроблемно.
  • Многопоточността улеснява много повече приложения.