multithreading java tutorial with examples
Ten samouczek wyjaśnia wszystko na temat wielowątkowości w języku Java, implementacji współbieżności, cyklu życia wątku, przykładu klasy wątku, wątku przy użyciu interfejsu uruchomionego:
Współbieżność w świecie komputerów to zdolność systemu (aplikacji, komputera lub języka programowania) do równoległego wykonywania kilku wystąpień programu lub aplikacji.
Uruchamiając instancje lub programy jednocześnie, zapewniamy wysoką przepustowość i wyższą wydajność, ponieważ możemy wykorzystać niewykorzystane zasoby, takie jak sprzęt systemu operacyjnego itp. Na przykład, jeśli system ma kilka procesorów, aplikacja może efektywnie wykorzystać te procesory i zwiększyć przepustowość.
=> Odwiedź tutaj ekskluzywną serię samouczków szkoleniowych Java.
Czego się nauczysz:
Co to jest wielowątkowość w Javie
W Javie wątki można traktować jako podstawę współbieżności. Wątek to wykonywalna, lekka jednostka, która uzyskuje dostęp do współdzielonych zasobów, a także do własnego stosu wywołań.
Aplikacja Java to jeden proces iw ramach tej aplikacji możemy mieć wiele wątków, aby osiągnąć współbieżność.
Wiemy, że aplikacja działająca w systemie może mieć wiele instancji i są to zwykle nazywane aplikacjami multi-doc. Te wystąpienia aplikacji nazywane są procesami. Każdemu z tych procesów jest przypisana jednostka wykonawcza zwana wątkiem.
W zależności od systemu operacyjnego i wymagań aplikacji, procesowi można przypisać pojedynczy wątek lub wiele wątków. Gdy procesowi aplikacji jest przypisanych wiele wątków, musimy wykonywać te wiele wątków jednocześnie.
' Ta technika wykonywania lub uruchamiania wielu wątków jednocześnie lub współbieżnie jest nazywana wielowątkowością ”.
Wielowątkowość oznacza po prostu, że - mamy więcej niż jeden wątek wykonujący się w tej samej aplikacji.
Język programowania Java ma wbudowaną obsługę wielowątkowości.
Na powyższym schemacie przedstawiono wielowątkowość. Jak pokazano, w aplikacji jest jednocześnie uruchomionych wiele wątków.
Na przykład, aplikacja komputerowa zapewniająca takie funkcje, jak edycja, drukowanie itp. jest aplikacją wielowątkową. W tej aplikacji, ponieważ drukowanie jest procesem w tle, możemy jednocześnie edytować dokumenty i drukować dokumenty, przypisując te funkcje do dwóch różnych wątków.
Wątki w aplikacjach wielowątkowych działają równolegle do siebie w sposób współbieżny. Tak więc wielowątkowość jest również częścią współbieżności w Javie. Należy pamiętać, że chociaż istnieje wiele wątków, współdzielą one obszar pamięci, oszczędzając w ten sposób pamięć. Ponadto wątki mogą łatwo zmieniać konteksty w mgnieniu oka.
Wielowątkowość jest głównie przydatna, ponieważ zapewnia równoczesne wykonywanie dwóch lub więcej części aplikacji. Dzięki temu aplikacja może wykorzystać czas procesora do maksimum, a czas bezczynności jest ograniczony do minimum.
Poniżej przedstawiono niektóre terminy, które powinniśmy znać w odniesieniu do środowiska wielowątkowego, ponieważ są one często używane.
Wielozadaniowość: W przypadku wielozadaniowości wykonywanych jest więcej niż jedno zadanie w tym samym czasie.
Wielowątkowość: Wielowątkowość, jak już wspomniano, jest procesem wykonywania wielu wątków jednocześnie.
jak utworzyć tablicę ciągów java
Przetwarzanie wieloprocesowe: W przypadku przetwarzania wieloprocesowego jednocześnie wykonywany jest więcej niż jeden proces. Podobnie jak w przypadku wielozadaniowości, ale w tym przypadku zaangażowany jest więcej niż jeden procesor.
Przetwarzanie równoległe: Przetwarzanie równoległe to technika, w której wiele procesorów pracuje jednocześnie w systemie komputerowym.
Po omówieniu wielowątkowości pojawia się pytanie, dlaczego w ogóle potrzebujemy wielowątkowości?
Korzyści z wielowątkowości
Wielowątkowość ma wiele zalet, które pomagają w efektywnym programowaniu.
Poniższe punkty wyjaśnią to.
# 1) Efektywne wykorzystanie systemów z jednym procesorem
Gdy w systemie jest tylko jeden procesor z jednym wątkiem, marnowany jest czas procesora. Gdy wątek jest zajęty korzystaniem z innych zasobów, takich jak IO, procesor jest bezczynny. Możemy to poprawić i lepiej wykorzystać procesor, korzystając z aplikacji wielowątkowych.
Używając wielowątkowości, jeśli jeden wątek jest obsługiwany przez procesor, drugi wątek może go wykorzystać. W przypadku wielu wątków czas bezczynności procesora zostanie znacznie skrócony.
# 2) Efektywne wykorzystanie wielu systemów CPU
Podobnie jak pojedyncze procesory, nawet w przypadku systemów z wieloma procesorami, aplikacje wielowątkowe mogą efektywnie wykorzystywać wiele procesorów.
# 3) Lepsze wrażenia użytkownika w zakresie responsywności i uczciwości
Szybkość reakcji systemu poprawia się w przypadku aplikacji wielowątkowych. Nie doświadczamy „Wiszący GUI” gdy mamy wiele wątków wykonujących różne zadania w aplikacji, a użytkownicy nie muszą długo czekać na odpowiedź na swoje żądania.
Podobnie, użytkownicy są właściwie usługami w systemach wielowątkowych.
Jak zaimplementować współbieżność w Javie
Pierwszą klasą, za pomocą której możemy zaimplementować współbieżność w Javie, jest java.lang.Thread klasa. Ta klasa Thread stanowi podstawę współbieżności w Javie.
Mamy też java.lang.Runnable interfejs, który może zostać zaimplementowany przez klasę Java, aby wyodrębnić zachowanie wątku. Do tworzenia zaawansowanych aplikacji możemy wykorzystać rozszerzenie java.util.concurrent pakiet dostępny od wersji Java 1.5.
Idąc dalej, szczegółowo omówimy współbieżność w Javie. Omówmy i zrozummy pojęcie wątków w Javie w tym samouczku. W naszych kolejnych samouczkach dotyczących wielowątkowości będziemy badać różne koncepcje wielowątkowości i współbieżności.
Co to jest wątek w Javie
Pojedynczy wątek można zdefiniować jako najmniejszą i lekką jednostkę przetwarzania. W Javie wątki są używane w programach używających klasy „Wątek”.
Wątki Java są dwojakiego rodzaju:
# 1) Wątek użytkownika: wątek użytkownika jest tworzony podczas pierwszego uruchomienia aplikacji. Następnie możemy utworzyć dowolną liczbę wątków użytkownika i demona.
# 2) Wątek demona: Wątki demona są używane głównie w tle i są używane do zadań takich jak czyszczenie aplikacji itp.
Wątki zmniejszają koszty utrzymania aplikacji. Zmniejsza również obciążenie aplikacji.
Przykład pojedynczego wątku pokazano poniżej:
public class Main{ public static void main (String [] args){ System.out.println('This is a thread'); } }
Powyższy program wyświetli komunikat „To jest wątek”, ponieważ podczas uruchamiania aplikacji tworzony jest wątek użytkownika. W powyższym programie główna funkcja jest punktem startowym aplikacji i tworzy wątek użytkownika.
Cykl życia nici
Poniższy diagram przedstawia cykl życia wątku w Javie.
Jak pokazano na powyższym diagramie, wątek w Javie ma następujące stany:
fig_cropper.swf, jak otworzyć
# 1) Nowość: Początkowo wątek właśnie utworzony z klasy wątku ma stan „nowy”. To jeszcze się nie zaczęło. Ten wątek jest również nazywany „Urodzony wątek” .
# 2) Możliwość uruchomienia: W tym stanie instancja wątku jest wywoływana przy użyciu metody 'początek' .
# 3) Bieganie: Wywoływana jest metoda startowa instancji wątku i wątek rozpoczyna wykonywanie. To jest stan pracy. Przeważnie harmonogram planuje i zarządza wątkami.
# 4) Zablokowany: W aplikacji jest wiele wątków. Te wątki muszą czekać na inny, ponieważ ich wykonanie musi być zsynchronizowane.
# 5) Zakończono: Po zakończeniu procesu wykonywania wątku wątek jest przerywany lub jego wykonywanie jest zatrzymywane.
Zatem najpierw tworzony jest wątek, następnie planowany, a później program planujący wykonuje wątek. Podczas gdy uruchomiony wątek może zostać zablokowany lub zawieszony w celu wykonania innej czynności. Następnie jest wznawiany i po zakończeniu przetwarzania wątek jest wykonywany.
Priorytety wątków
Priorytet wątku decyduje o tym, jak jeden wątek ma być traktowany w odniesieniu do innych wątków w aplikacji. Priorytet wątku to liczba całkowita.
Poniżej wymieniono kilka punktów, o których należy pamiętać o priorytetach wątków:
- Priorytety wątków to liczby całkowite.
- Korzystając z priorytetu wątków, możemy zdecydować, kiedy powinniśmy przełączyć się z jednego wątku w stanie uruchomionym na inny. Jest to proces przełączania kontekstów, w którym przełączamy konteksty wątków.
- W każdej chwili wątek może dobrowolnie zwolnić kontrolę nad procesorem. Wtedy wątek o najwyższym priorytecie może przejąć kontrolę.
- Podobnie, wątek o wyższym priorytecie może wyprzedzać każdy inny wątek o niższym priorytecie.
- Klasa Thread udostępnia metodę setPriority (), która służy do ustawiania priorytetu wątku.
- Możemy również użyć stałych MIN_PRIORITY, MAX_PRIORITY lub NORM_PRIORITY zamiast liczb całkowitych.
Utwórz wątek
Możemy utworzyć wątek na jeden z następujących sposobów:
- Rozszerzanie klasy Java „Thread”.
- Wdrażanie „Runnable”.
Rozszerzanie klasy „wątku” Java
Klasa „Thread” zawiera konstruktory i metody, które pozwalają nam tworzyć i wykonywać operacje na obiekcie wątku. Wewnętrznie klasa Thread implementuje interfejs Runnable, a także rozszerza klasę Object.
Poniższa tabela zawiera podsumowanie różnych konstruktorów i metod klasy Thread ().
Budowniczy/ | Prototyp | Opis |
---|---|---|
sen | publiczny sen pustki (długie milisekundy) | Wykonywanie bieżącego wątku jest zatrzymywane na określone milisekundy. |
Konstruktor Thread () | Wątek() | Domyślny konstruktor do tworzenia obiektu Thread. |
Wątek (nazwa ciągu) | Konstruktor do tworzenia obiektu Thread o określonej nazwie. | |
Wątek (Runnable r) | Utwórz wystąpienie Thread z określonym obiektem interfejsu Runnable. | |
Wątek (Runnable r, nazwa ciągu) | Utwórz wystąpienie Thread z określonym obiektem interfejsu Runnable i podaną nazwą | |
biegać | public void run () | Run wykonuje akcję dla wątku. Wywołuje wątek. |
początek | public void start () | Służy do uruchamiania wykonywania wątku. Wewnętrznie maszyna JVM wywołuje metodę run () w tym wątku. |
Przystąp | public void join () | Poczekaj, aż nić umrze |
publiczne połączenie puste (długie milisekundy) | Poczekaj na określone milisekundy, aby wątek umarł. | |
getPriority | public int getPriority () | Zwróć priorytet wątku |
Ustaw priorytet | public int setPriority (int priorytet) | Zmień priorytet wątku na określony priorytet |
getName | public String getName () | zwraca nazwę wątku. |
setName | public void setName (nazwa ciągu) | Ustaw nazwę wątku na określony ciąg |
currentThread | public Thread currentThread () | Zwraca odwołanie do wątku, który jest aktualnie aktywny |
getId | public int getId () | Zwróć identyfikator wątku |
getState () | public Thread.State getState () | Zwraca aktualny stan wątku |
żyje | public boolean isAlive () | Sprawdź, czy wątek żyje i zwróć wartość true, jeśli tak. |
wydajność | publiczny void yield () | Tymczasowo wstrzymuje bieżący wątek i zezwala na wykonywanie innych wątków. |
isDaemon | public boolean isDaemon () | Sprawdź, czy wątek jest wątkiem demona; zwraca prawdę, jeśli tak. |
setDaemon | public void setDaemon (boolean b) | Ustaw wątek jako wątek demona, jeśli b = true; inaczej ustawiony jako wątek użytkownika. |
przerwać | publiczne przerwanie void () | Przerwij bieżący wątek. |
isInterrupted | public boolean isInterrupted () | Sprawdź, czy wątek jest przerwany. |
przerwał | public static boolean przerwane () | Sprawdź, czy bieżący wątek został przerwany. |
dumpStack | Statyczne void dumpStack () | Drukuje ślad stosu bieżącego wątku do standardowego strumienia błędów. |
zawieszać | public void suspend () | Zawiesza wszystkie wątki. (** metoda jest przestarzała w najnowszych wersjach Java) |
wznawianie | public void resume () | Wznów zawieszony wątek. (** metoda jest przestarzała w najnowszych wersjach Java) |
zatrzymać | publiczne void stop () | Zatrzymuje nić. (** metoda jest przestarzała w najnowszych wersjach Java) |
Omówimy te metody wątków w naszym następnym samouczku dotyczącym wielowątkowości.
Rozpoczynanie wątku
Metoda start (), która jest używana do uruchamiania wątku, wykonuje następujące kroki:
- Uruchamia nowe wystąpienie wątku z nowym CallStack.
- Stan wątku został zmieniony z nowego na działający.
- Kiedy przychodzi kolej na wątek, wykonuje metodę run ().
Implementacja interfejsu „Runnable”
Wystąpienie wątku można również utworzyć za pomocą interfejsu Runnable. Aby utworzyć wystąpienie wątku, klasa, której obiekty mają być wykonywane przez wątek, powinna implementować interfejs Runnable.
Interfejs Runnable ma tylko jedną metodę:
public void run () => this method is used to execute the thread.
Przykład klasy wątku
Teraz zademonstrujemy wątek w Javie przy użyciu klasy wątku.
//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...'); } }
Wynik
Wątek Java wykorzystujący Runnable Interface
Poniższy przykład ilustruje użycie interfejsu Runnable do tworzenia wystąpienia wątku.
//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...'); } }
Wynik
Jak zatrzymać wątek w Javie
Widzieliśmy powyższe przykłady wątków. Z tych przykładów wiemy, że gdy metoda run zakończy wykonywanie, wątek zatrzymuje się lub zatrzymuje się również z powodu pewnych wyjątków.
Wcześniejsze wersje języka Java miały metodę stop () w klasie Thread, której można było użyć do bezpośredniego zatrzymania wątku. Ale teraz został wycofany ze względów bezpieczeństwa. Dlatego musimy zastosować inne metody, aby zatrzymać wykonywany wątek.
Istnieją dwie metody zatrzymania nici.
- Używanie zmiennej logicznej Volatile
- Korzystanie z przerwań.
W tej sekcji omówimy obie te metody zatrzymywania wątku.
Korzystanie z lotnej zmiennej boolowskiej
W tej metodzie utrzymujemy zmienną logiczną say flag, aby zatrzymać wątek. Wątek działa tak długo, jak długo zmienna boolowska ma wartość true. W momencie, gdy stanie się fałszywy, wątek zostaje zatrzymany.
Specjalnością tej metody jest to, że deklarujemy zmienną boolowską jako „ lotny ”Tak, że jest zawsze odczytywany z pamięci głównej, a program nie może buforować go w pamięci podręcznej procesora. W ten sposób nie będzie żadnej różnicy w ustawionych i odczytanych wartościach.
Implementacja zatrzymania wątku za pomocą lotnej zmiennej boolowskiej jest pokazana poniżej.
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(); } }
Wynik
Uwaga: Tutaj pokazaliśmy tylko część wyników. Wątek może działać przez kilka minut przed zatrzymaniem. Abyśmy mogli uzyskać różne wyniki w różnych systemach.
Korzystanie z przerwań
Tutaj wątek jest zatrzymywany przy użyciu metody przerwania (), jak już omówiliśmy powyżej w metodach klasy wątków. Metoda przerwania () ustawia stan wątku jako przerwany. Ten stan jest przekazywany do pętli while metody run (). Stan przerwania możemy uzyskać za pomocą metodyrupted ().
Poniższy program demonstruje użycie metody breaking () do zatrzymania wątku.
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(); } }
Wynik
Często Zadawane Pytania
Pytanie 1) Dlaczego używamy wielowątkowości w Javie?
Odpowiedź: Wielowątkowość umożliwia współbieżne lub jednoczesne wykonywanie dwóch lub więcej wątków w aplikacji. Równoczesne wykonywanie maksymalizuje przepustowość, a także maksymalnie wykorzystuje procesor.
P # 2) Co to jest wielowątkowość? Jakie są jego rodzaje?
Odpowiedź: Wielowątkowość oznacza wykonywanie więcej niż jednego wątku. To wykonanie może być współbieżne lub równoległe. Zatem wielowątkowość ma dwa typy, tj. Współbieżną lub równoległą.
P # 3) Co to jest wielowątkowość a wieloprocesowość?
Odpowiedź: W przypadku wielowątkowości istnieje wiele wątków dla tych samych lub różnych procesów i te wątki są wykonywane jednocześnie w celu zwiększenia szybkości obliczeniowej systemu. W przypadku przetwarzania wieloprocesowego system ma więcej niż dwa procesory i wiele procesów jest wykonywanych jednocześnie.
P # 4) Jakie są zalety wielowątkowości w Javie?
Odpowiedź: Korzystając z wielowątkowości możemy jednocześnie wykonywać różne części aplikacji za pomocą wątków. Wielowątkowość zwiększa przepustowość systemu. Wielowątkowość maksymalizuje również wykorzystanie procesora, ponieważ różne wątki stale go używają.
P # 5) Czy wielowątkowość jest dobra w grach?
Odpowiedź: Tak, szczególnie w przypadku nowoczesnych gier.
Wniosek
Chodzi o wprowadzenie wielowątkowości. Omówiliśmy współbieżność i wielowątkowość w Javie w tym samouczku. Omówiliśmy tworzenie wątku z klasą Thread, a także interfejsem Runnable i dostarczyliśmy odpowiednie przykłady.
Poznaliśmy również szczegółowo koncepcje pojedynczego wątku i jego tworzenia. Pojęcia dotyczące wątków, w tym cykl życia wątku, zatrzymywanie wątku, typy wątków itp. Zostały omówione w tym samouczku.
Omówiliśmy również szczegółowo wielowątkowość i współbieżność w Javie. Pod koniec tego samouczka czytelnik powinien być w stanie łatwo zrozumieć koncepcje współbieżności i wielowątkowości, a także wątki w Javie.
=> Obejrzyj serię prostych szkoleń dotyczących języka Java.
rekomendowane lektury
- Wielowątkowość w C ++ z przykładami
- Wątki Java z metodami i cyklem życia
- Thread.Sleep () - Metoda Thread Sleep () w języku Java z przykładami
- Samouczek JAVA dla początkujących: ponad 100 praktycznych samouczków wideo Java
- Samouczek dotyczący refleksji w języku Java z przykładami
- Java String zawiera () Samouczek dotyczący metody z przykładami
- Postrzępiona tablica w Javie - samouczek z przykładami
- Samouczek klasy skanera Java z przykładami