
Michael Fisher
0
3405
415
Wielowątkowość to metoda pisania kodu do równoległego wykonywania zadań. Java ma doskonałą obsługę pisania wielowątkowego kodu od pierwszych dni istnienia Java 1.0. Ostatnie udoskonalenia języka Java zwiększyły możliwości strukturyzacji kodu w celu włączenia wielowątkowości w programach Java.
W tym artykule porównujemy kilka z tych opcji, abyś mógł lepiej ocenić, której opcji użyć do następnego projektu Java Love GitHub? 4 powody, dla których powinieneś hostować swój kod na BitBucket Love GitHub? 4 powody, dla których powinieneś przechowywać swój kod na BitBucket Musisz pomyśleć o tym, gdzie zamierzasz przechowywać swój kod. Prawdopodobnie słyszałeś o GitHub. Nic dziwnego. GitHub jest używany przez osoby prywatne i przedsiębiorstwa do hostowania kodu, współpracy przy dokumentacji… t.
Metoda 1: Rozszerzenie klasy wątku
Java zapewnia Wątek klasa, którą można rozszerzyć w celu wdrożenia biegać() metoda. Ta metoda run () służy do implementacji zadania. Jeśli chcesz rozpocząć zadanie we własnym wątku, możesz utworzyć instancję tej klasy i wywołać ją początek() metoda. To uruchamia wykonywanie wątku i uruchamia się do końca (lub kończy się w wyjątku).
Oto prosta klasa wątków, która śpi tylko przez określony czas jako sposób na symulację długotrwałej operacji.
klasa publiczna MyThread rozszerza Wątek private int sleepFor; public MyThread (int sleepFor) this.sleepFor = sleepFor; @Override public void run () System.out.printf ("[% s] początek wątku \ n", Thread.currentThread (). ToString ()); spróbuj Thread.sleep (this.sleepFor); catch (InterruptedException ex) System.out.printf ("[% s] zakończenie wątku \ n", Thread.currentThread (). toString ());
Utwórz instancję tej klasy wątku, podając liczbę milisekund do uśpienia.
MyThread worker = new MyThread (sleepFor);
Rozpocznij wykonywanie tego wątku roboczego, wywołując jego metodę start (). Ta metoda natychmiast zwraca kontrolę do programu wywołującego, nie czekając na zakończenie wątku.
worker.start (); System.out.printf ("[% s] główny wątek \ n", Thread.currentThread (). ToString ());
A oto wynik działania tego kodu. Wskazuje, że diagnostyka głównego wątku jest drukowana przed wykonaniem wątku roboczego.
[Wątek [główny, 5, główny]] główny wątek [Wątek [Wątek-0,5, główny]] początek wątku [Wątek [Wątek-0,5, główny]] zakończenie wątku
Ponieważ po uruchomieniu wątku roboczego nie ma już żadnych instrukcji, wątek główny czeka na zakończenie wątku roboczego przed zakończeniem programu. Dzięki temu wątek roboczy może wykonać swoje zadanie.
Metoda 2: Używanie wystąpienia wątku z możliwością uruchomienia
Java zapewnia także interfejs o nazwie Runnable który może zostać zaimplementowany przez klasę robotniczą w celu wykonania zadania w jej klasie biegać() metoda. Jest to alternatywny sposób tworzenia klasy robotniczej w przeciwieństwie do rozszerzania Wątek klasa (opisana powyżej).
Oto implementacja klasy robotniczej, która teraz implementuje Runnable zamiast rozszerzać Thread.
klasa publiczna MyThread2 implementuje Runnable // to samo co powyżej
Zaletą implementacji interfejsu Runnable zamiast rozszerzania klasy Thread jest to, że klasa procesu roboczego może teraz rozszerzyć klasę specyficzną dla domeny w ramach hierarchii klas.
Co to znaczy?
Powiedzmy na przykład, że masz Owoc klasa, która realizuje pewne ogólne cechy owoców. Teraz chcesz wdrożyć Papaja klasa, która specjalizuje się w niektórych cechach owoców. Możesz to zrobić, mając Papaja klasa przedłużyć Owoc klasa.
public class Fruit // owoce specyficzne tutaj public class Papaya rozszerza Fruit // nadpisuje zachowanie specyficzne dla papaya tutaj
Załóżmy teraz, że masz jakieś czasochłonne zadanie, które Papaya musi wesprzeć, które można wykonać w osobnym wątku. Ten przypadek można rozwiązać, wprowadzając funkcję Papna Runnable i udostępniając metodę run (), w której to zadanie jest wykonywane.
public class Papaya rozszerza Fruit implementuje Runnable // przesłonięcie zachowania specyficzne dla papaya tutaj @Override public void run () // tutaj czasochłonne zadanie.
Aby rozpocząć wątek roboczy, należy utworzyć instancję klasy robotniczej i przekazać ją instancji wątku podczas tworzenia. Po wywołaniu metody start () wątku zadanie jest wykonywane w osobnym wątku.
Papaya papaya = new Papaya (); // ustaw właściwości i wywołaj tutaj metody papai. Wątek w wątku = nowy wątek (papaya); thread.start ();
I to jest krótkie podsumowanie tego, jak używać Runnable do implementacji zadania wykonywanego w wątku.
Metoda 3: Wykonaj Runnable With ExecutorService
Począwszy od wersji 1.5, Java zapewnia ExecutorService jako nowy paradygmat tworzenia i zarządzania wątkami w programie. Uogólnia koncepcję wykonywania wątków, abstrahując od tworzenia wątków.
Wynika to z faktu, że zadania można uruchamiać w ramach puli wątków tak samo łatwo, jak dla każdego zadania osobny wątek. Umożliwia to Twojemu programowi śledzenie i zarządzanie liczbą wątków używanych do zadań roboczych.
Załóżmy, że masz 100 zadań roboczych oczekujących na wykonanie. Jeśli uruchomisz jeden wątek na pracownika (jak pokazano powyżej), będziesz mieć 100 wątków w swoim programie, co może prowadzić do wąskich gardeł w innym miejscu programu. Zamiast tego, jeśli użyjesz puli wątków, powiedzmy wstępnie przydzielonych 10 wątków, twoje 100 zadań zostanie wykonanych przez te wątki jeden po drugim, aby twój program nie był głodny zasobów. Ponadto wątki z puli wątków można skonfigurować tak, aby zawieszały się w celu wykonywania dodatkowych zadań.
Usługa Executor akceptuje Runnable zadanie (wyjaśnione powyżej) i uruchamia je w odpowiednim czasie. The Zatwierdź() Metoda, która akceptuje zadanie Runnable, zwraca instancję klasy o nazwie Przyszłość, co pozwala dzwoniącemu śledzić status zadania. W szczególności otrzymać() Metoda pozwala rozmówcy poczekać na zakończenie zadania (i zapewnia kod powrotu, jeśli istnieje).
W poniższym przykładzie tworzymy ExecutorService przy użyciu metody statycznej newSingleThreadExecutor (), który, jak wskazuje nazwa, tworzy pojedynczy wątek do wykonywania zadań. Jeśli więcej zadań zostanie przesłanych podczas działania jednego zadania, usługa ExecutorService ustawia w kolejce te zadania w celu ich dalszego wykonania.
Implementacja Runnable, której tu używamy, jest taka sama jak opisana powyżej.
ExecutorService esvc = Executors.newSingleThreadExecutor (); Runnable worker = new MyThread2 (sleepFor); Future future = esvc.submit (pracownik); System.out.printf ("[% s] główny wątek \ n", Thread.currentThread (). ToString ()); future.get (); esvc.shutdown ();
Należy zauważyć, że usługa ExecutorService musi zostać poprawnie zamknięta, gdy nie jest już potrzebna do dalszego przesyłania zadań.
Metoda 4: Wywołanie używane z ExecutorService
Począwszy od wersji 1.5, Java wprowadziła nowy interfejs o nazwie Do wywołania. Jest podobny do starszego interfejsu Runnable z tą różnicą, że metoda wykonania (wywołana połączenie() zamiast biegać()) może zwrócić wartość. Ponadto może również zadeklarować, że an Wyjątek można wyrzucić.
Usługa ExecutorService może również akceptować zadania realizowane jako Do wywołania i zwraca a Przyszłość z wartością zwracaną przez metodę po zakończeniu.
Oto przykład Mango klasa, która rozszerza Owoc zdefiniowana wcześniej klasa i implementuje Do wywołania berło. Kosztowne i czasochłonne zadanie jest wykonywane w obrębie połączenie() metoda.
klasa publiczna Mango rozszerza Fruit implementuje Callable public Integer call () // drogie obliczenia tutaj zwróć nową Integer (0);
A oto kod do przesłania instancji klasy do ExecutorService. Poniższy kod również czeka na zakończenie zadania i wyświetla jego wartość zwracaną.
ExecutorService esvc = Executors.newSingleThreadExecutor (); MyCallable worker = new MyCallable (sleepFor); Future future = esvc.submit (pracownik); System.out.printf ("[% s] główny wątek \ n", Thread.currentThread (). ToString ()); System.out.println („Zwrócono zadanie:” + future.get ()); esvc.shutdown ();
Co wolisz?
W tym artykule poznaliśmy kilka metod pisania wielowątkowego kodu w Javie. Obejmują one:
- Rozszerzenie Wątek klasa jest najbardziej podstawowa i jest dostępna z Java 1.0.
- Jeśli masz klasę, która musi rozszerzyć inną klasę w hierarchii klas, możesz zaimplementować Runnable berło.
- Bardziej nowoczesnym narzędziem do tworzenia wątków jest ExecutorService który może zaakceptować instancję Runnable jako zadanie do uruchomienia. Zaletą tej metody jest to, że do wykonywania zadań można użyć puli wątków. Pula wątków pomaga w ochronie zasobów poprzez ponowne użycie wątków.
- Na koniec możesz także utworzyć zadanie, implementując Do wywołania interfejs i przesłanie zadania do usługi ExecutorService.
Które z tych opcji wykorzystasz w następnym projekcie? Daj nam znać w komentarzach poniżej.