Wątki – Runnable oraz Callable

Wątki – Runnable oraz Callable

Cześć!

Tematem poprzedniego wpisu programistycznego były wątki. Opisałem kwestie ogólne, takie jak:

  • tworzenie wątku po klasie Thread
  • cykl życia wątku
  • przerywanie wątku

Jeśli nie miałeś okazji przeczytać postu, kliknij tutaj i nadrób zaległości. Dzisiaj chciałbym skupić się na dwóch interfejsach związanych z wątkami: Runnable oraz Callable. Do dzieła!

Tworzenie nowego wątku implementując interfejs Runnable

     Poza „tradycyjnym” sposobem tworzenia wątku który dziedziczy po klasie Thread możemy stworzyć wątek implementując interfejs „Runnable” i przysłonić metodę „run”. Tak to wygląda w praktyce:

Stworzenie wątku BiegajacyRunnable za pomocą interfejsu Runnable.

Jak widać, ciałem wątku jest implementacja (czy przysłonięcie) metody run z interfejsu Runnable. Można też stworzyć wątek posługując się klasami anonimowymi:

Stworzenie wątku (Runnable) biegajacyThread za pomocą klas anonimowych.

Klasy anonimowe to klasy definiowane w kodzie, które mają dokładnie jedną instancję

Interfejs Runnable jest interfejsem funkcyjnym a co za tym idzie, zapis ten można uprościć stosując wyrażenie lambda:

Stworzenie wątku za pomocą lambdy.

Interfejs funkcyjny to interfejs, który ma jedną abstrakcyjną metodę.

Dlaczego Runnable?

     Często zdarza się, że w aplikacjach musimy wykorzystać mechanizm wielokrotnego dziedziczenia, czyli chcemy przykładowo stworzyć oraz zdefiniować klasę, która ma właściwości wątku jednocześnie rozszerzając właściwości jakiejś innej klasy. Ponieważ w Javie fizycznie wielokrotne dziedziczenie nie jest możliwe, idealnym rozwiązaniem w tym przypadku jest implementacja interfejsu Runnable.

Tworzenie nowego wątku implementując interfejs Callable

     Wątek możemy również stworzyć implementując interfejs „Callable”, przysłaniając tym razem metodę „call”, która zwraca obiekt typu, którego użyliśmy przy implementacji Callable. Tak to wygląda w praktyce:

Stworzenie wąku BiegajacyCallable za pomocą interfejsu Callable.

Jak widać, kod który ma się wykonać w nowym wątku umieszcza się w metodzie „call”.

Dlaczego Callable?

      Podstawową różnicą między Runnable i Callable (to pytanie również często pojawia się na rozmowach kwalifikacyjnych) jest to, że Callable wymusza zwrócenie obiektu. Dodatkowo warto zauważyć, ze metoda Callable udostępnia możliwość rzucenia wyjątku kontrolowanego (checked exception).

Co wybrać?

Do tej pory poznaliśmy wspólnie trzy sposoby tworzenia wątków. 

  • Pierwszym sposobem jest klasyczne rozszerzanie klasy Thread (prawdopodobnie najrzadziej wykorzystywanie rozwiązanie). Należy pamiętać, że podczas dziedziczenia klasa pochodna powinna być typem klasy nadrzędnej. Czyli rzadko będziemy spotykać się z sytuacją, gdzie tworzona przez nas klasa będzie musiała rozszerzać klasę Thread, aby rozszerzać jej funkcjonalność.
  • Pozostałymi sposobami to implementacja za pomocą interfejsów Runnable i Callable. Wybierając się na któryś z nich należy przede wszystkim pamiętać, że metoda „run” z interfejsu Runnable jest typu void, gdzie metoda call z Callable zwraca wynik obliczeń. Dodatkowo, w przypadku Callable możemy zadeklarować wyjątki kontrolowane (na co nie pozwala nam metoda run). Zatem wszystko można dostosować do potrzeb naszego kodu.

Podsumowanie

     Preferowanym rozwiązaniem jest implementacja interfejsu Runnable lub Callable. Dzięki interfejsom dochodzimy do sytuacji, w której nasz kod jest luźno powiązany, ponieważ kod wątku różni się od klasy, która przypisuje zadanie do wątku. Przede wszystkim wymaga to mniej pamięci i pozwala klasie dziedziczyć dowolną inną klasę. Mam nadzieje, że sposoby tworzenia wątków są już jasne. Za dwa tygodnie omówię kolejny temat z wątków, czyli wielowątkowość.

 

Pozdrawiam serdecznie,
biegajacyprogramista.pl

Dodaj komentarz

18 − eighteen =

Close Menu