Всяко приложение може да има множество процеси (екземпляри). Всеки от този процес може да бъде присвоен или като единична нишка, или като множество нишки. В този урок ще видим как да изпълняваме множество задачи едновременно и също така ще научим повече за нишките и синхронизирането между нишките.
В този урок ще научим:
- Какво е единична нишка
- Какво е 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
Жизненият цикъл на една нишка:
Има различни етапи от жизнения цикъл на резбата, както е показано на горната диаграма:
- Ново
- Изпълним
- Бягане
- Очакване
- Мъртъв
- Ново: В тази фаза нишката се създава с помощта на клас "Thread class". Тя остава в това състояние, докато програмата стартира нишката. Известен е още като родена нишка.
- Изпълним: На тази страница екземплярът на нишката се извиква с начален метод. Контролът на нишката се дава на планировчика, за да завърши изпълнението. Зависи от програмиста дали да стартирате нишката.
- Изпълнява се: Когато нишката започне да се изпълнява, тогава състоянието се променя на "работещо" състояние. Планировчикът избира една нишка от пула нишки и тя започва да се изпълнява в приложението.
- Изчакване: Това е състоянието, когато нишката трябва да изчака. Тъй като в приложението се изпълняват множество нишки, има нужда от синхронизация между нишките. Следователно една нишка трябва да изчака, докато другата нишка бъде изпълнена. Следователно това състояние се нарича състояние на изчакване.
- 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 и как да използваме единични и много нишки.
- При многопоточност потребителите не са блокирани, тъй като нишките са независими и могат да извършват множество операции едновременно
- Различни етапи от жизнения цикъл на конеца са,
- Ново
- Изпълним
- Бягане
- Очакване
- Мъртъв
- Научихме и за синхронизацията между нишките, които помагат на приложението да работи безпроблемно.
- Многопоточността улеснява много повече приложения.