Wątki w Javie - podstawy

Pisząc program dość często zachodzi konieczność wykonywania kilku czynności na raz (np. ściąganie plików, wyświetlanie obrazków, animacja, obsługa użytkownika). W Javie wszystkie te elementy mogą wykonywać się "jednocześnie" poprzez zastosowanie wątków.

Pierwszą czynnością przy tworzeniu wątków jest stworzenie obiektu klasy implementującej interfejs Runnable, interfejs ten ma tylko jedną metodę run(), w której zamieścimy kod naszego wątku.
public interface Runnable {
 void run();
}
Szkielet klasy implementującej interfejs Runnable:
class Watek implements Runnable {
 void run() {
  // kod, który ma zostać wywołany przez wątek
 }
}
Samo utworzenie w pełni sprawnego wątku to stworzenie obiektu klasy Thread z przekazaną do jej konstruktora referencją obiektu klasy implementującej interfejs Runnable.
Runnable obiekt = new Watek();
Thread pierwszyWatek = new Thread(obiekt);
Tak utworzony obiekt jest już pełnokrwistym wątkiem. Możemy go uruchomić za pomocą metody start() (wywołane zostanie ciało metody run()).
pierwszyWatek.start();
Spróbujmy wykorzystać naszą wiedzę do napisania prostej aplikacji, której zadaniem będzie wyświetlanie na ekranie za pomocą wątków różnych napisów. Każdy napis to osobny wątek. Ciało metody run() to pętla for, która co określoną liczbę milisekund wyświetli odpowiedni napis. Wartość opóźnienia w wyświetlaniu będzie losowana z zakresu od 0 do 2000 milisekund (pomiędzy 0 a 2 sekundami). Do losowania liczb wykorzystamy metodę rand() z klasy Math, a do zatrzymania wątku na określony czas metodę sleep() dostepną w klasie Thread. Pętla wykona się 10 razy po czym zakończy swoje zadanie, co za tym idzie wątek również zostanie zakończony (koniec metody run()).
/**
 * Wykorzystanie wątków
 * @author kodatnik.blogspot.com
 */

// klasa implementująca interfejs Runnable
class Napis implements Runnable {
 // pole napis przechowujące łańcuch tekstowy
 private String napis;

 // konstruktor klasy
 public Napis(String napis) {
  this.napis = napis;
 }

 // zaimplementowana metoda run
 public void run() {
  // pętla dziesięciokrotna
  for (int i = 0; i < 10; i++) {
   // wyświetlamy napis
   System.out.println(napis);
   try {
    // usypiamy wątek na losową liczbę milisekund (od 0 do 2000)
    Thread.sleep((int)(Math.random()*2000));
   } catch(InterruptedException e){}
   }
  }
}

// klasa tworząca i uruchamiająca wątki
public class Watki {
 public static void main(String [] args) {
  // rozpoczynamy działanie metody main()
  System.out.println("Tworzenie wątków w Javie.");
  
  // tworzymy trzy obiekty klasy napis z różnymi łańcuchami tekstowymi
  Napis napisPierwszy = new Napis("Kodatnik");
  Napis napisDrugi = new Napis("Java");
  Napis napisTrzeci = new Napis("Wątek");

  // tworzymy trzy wątki
  Thread watekPierwszy = new Thread(napisPierwszy);
  Thread watekDrugi = new Thread(napisDrugi);
  Thread watekTrzeci = new Thread(napisTrzeci);

  // uruchamiamy wątki
  watekPierwszy.start();
  watekDrugi.start();
  watekTrzeci.start();
  
  // kończymy działanie metody main() wyświetlając komunikat
  System.out.println("Metoda main(), główny wątek aplikacji, zakończyła swoje działanie.");
 }
}
Poniżej wynik działania aplikacji (za każdym razem będzie on inny). Zauważ, że metoda main() zakończyła swoje działanie od razu.
Tworzenie wątków w Javie.
Metoda main(), główny wątek aplikacji, zakończyła swoje działanie.
Kodatnik
Java
Wątek
Kodatnik
Wątek
Java
Wątek
Kodatnik
Java
Kodatnik
Java
Wątek
Kodatnik
Java
Wątek
Java
Kodatnik
Wątek
Java
Wątek
Kodatnik
Wątek
Java
Wątek
Java
Kodatnik
Kodatnik
Java
Wątek
Kodatnik
Java
Wątek
Wątek
Java
Kodatnik
Wątek
Kodatnik
Java
Kodatnik
Wątek
Java
Kodatnik
Kodatnik
Wątek
Wątek
Java
Kodatnik
Kodatnik
Kodatnik
Java
Wątek
Kodatnik
Wątek
Java
Kodatnik
Wątek
Java
Wątek
Java
Java
Możemy dodać nowe wątki z innymi napisami i sprawdzić działanie programu. Inny przykład wykorzystania wątków zaprezentowałem w poście Zegar w Swingu. W kolejnym postach zastanowimy się jak zatrzymywać wątki i jak je synchronizować.
Innym sposobem tworzenia wątków jest rozszerzenie możliwości klasy Thread. Przesłaniamy metodę run() i wątek gotowy. Ten sposób ma jednak kilka wad, jeśli nasza klasa będzie dziedziczyć z innej klasy to nie może już rozszerzać możliwości klasy Thread (dziedziczenie w Javie jest jednokrotne). Rozwiązanie z interfejsem nie narzuca nam takich ograniczeń.
Pisząc dowolny program w Javie korzystamy, nawet nie wiedząc o tym, z wątków. Każda aplikacja jest uruchamiana w Wirtualnej Maszynie Javy jako osobny wątek. Możliwe zatem jest jest wstrzymanie za pomocą metody Thread.sleep().


9 Komentarzy - Wątki w Javie - podstawy

CamilYedrzejuq pisze...

Spoko wstęp. Napisz coś o zarządzaniu pulą wątków. Sposoby synchronizacji. Może o frameworku fork/join/

java przykłady pisze...

Ciekawy tekst, obecnie wielowątkowość staje się coraz popularniejszym sposobem na przyśpieszenie obliczeń

Anonimowy pisze...

Bardzo ładnie opisany i skomentowany program. No i jeszcze z zachowaniem zasad hermetyzacji. Dobrze wykonana robota. Aż miło.

Programistyczny pisze...

Wielkie dzięki za artykuły o Javie, dużo mi pomogły. Szkoda, że brak kolejnych, pozdrawiam!

Unknown pisze...

Dobra blog! Wiele ciekawych rzeczy i na pewno mi się przyda :)

Anonimowy pisze...

przerwales pisanie tego bloga? why? :)

obiady domowe z dowozem Łowicz pisze...

Java dzika Java

catering dietetyczny pisze...

lubię jave - fajny blog ! stare klimaty !

https://coderslab.pl/pl/javascript-developer-react pisze...

Bardzo dobrze opisane i wyjaśnione zagadnienie wątków. Wiele osób nie jest w stanie tego ogarnąć w Javie. Nie jest to takie trudne, ale właśnie trzeba wpaść na taki tekst żeby to dobrze zrozumieć. Super robota!

Prześlij komentarz

Możesz użyć niektórych tagów HTML, takich jak <b>, <i>, <u>, <a> Nie spamuj :)

Popularne posty