Wielowątkowość w java
Dostępne mechanizmy
Java posiada wbudowaną obsługi wielu wątków
Dostarcza mechanizmy synchronizowania wątków
Pozwala na łatwe posługiwanie się wieloma wątkami
Wielowątkowość - cechy
Na pojedynczym procesorze aplikacja jest wykonywana współbieżnie.
Przełączaniem poszczególnych wątków zajmuje się JVM i na różnych platformach może się odbywać inaczej
Na maszynach z wieloma procesorami może być wykonywana równolegle.
Cel stosowania wielowątkowości
Uproszczenie programowania aplikacji wielomodułowych pracujących z różną prędkością
Drukowanie
Komunikacja z użytkownikiem
Obliczenia
Prezentacja wyników cząstkowych
Deklaracja w Javie
Podklasa klasy Thread
Implementacja interfejsu Runnable
Interfejs ten pochodzi z pakietu java.lang, jego deklaracja:
public interface Runnable{
void run(); }
Każda klasa używająca tego interfejsu musi posiadać metodę run().
Deklaracja - klasa potomna Thread
Dostęp do wszystkich metod kontrolujących wątek zdefiniowanych w klasie Thread
W klasie, która jest wątkiem oprócz konstruktora musi wystąpić metoda run()
W run() zdefiniowane są wszystkie działania wykonywane przez wątek
Przykałd
class Watek extends Thread {
String wysuń - "";
public Watek(String str, int numeru)//Konstruktor
{…}
public void run()//Główna metoda wątku
{…}
}
Deklaracja - klasa potomna Thread
public Watek(String str, int numer) {
super(str); //Konstruktor nadklasy, ustawia nazwę wątku
// Ustawienie wcięcia z jakim będzie wyświetlana
// nazwa Wątku
for (int i = 1; i < numer; i++) wysuń = wysuń + "\t"; }
Deklaracja - interfejs Runnable
Wątek ma oprócz własności wątku jeszcze inne własności
Interfejs Runnable ma tylko jedną klasę run()
Klasa Thread i inne klasy implementują interfejs Runnable, dzięki temu mamy dostęp do własności różnych klas
Deklaracja - interfejs Runnable
class Watek implements Runnable {
String wysuń - "";
// W polu danych bieżący przechowywana będzie referencja do wątku,w którym wykonana zostanie klasa Watek
Thread bieżący;
public Watek {int numer) {...}
public void run()
{…} }
Deklaracja - interfejs Runnable
public Watek {int numer) {
// metoda statyczna currentThread() klasy Thread zwąca referencję do bieżącego wątku
bieżący = Thread. currentThread();
for (int i = 1; i < numer; i++)
wysuń = wysuń + "\t"; }
Deklaracja - interfejs Runnable
public void run(){ for(inti = 0; i < 4; i++) {
// dzięki referencji bieżący możemy na rzecz tego wątku wykonać metodę getName() (z klasy Thread)
System.outprintl n (wysuń + i + "" + bieżący. getName());
try{
bieżący.sleep((int)(Math.random()*1000)); }
catch (lnterruptedException e) {} }
System, out.printl n (wysuń +• biezacy.getName()+ " koniec"); }
Stany wątków
Nowy wątek
Wykonywany
Nie wykonywany
Zakończony
Stany wątków - nowy wątek
Thread Watek = new KlasaWatku();
Tylko tworzy obiekt klasy Thread nie rezerwuje zasobów systemowych
Możemy wykonać metodę start() i stop()
Przy próbie wywołania innych metod otrzymujemy wyjątek
IIlegał ThreadStateException
Stany wątków - wykonywany
Thread Walek = new KlasaWalku();
Watek.start();
Tworzy zasoby systemowe potrzebne douruchomienia wątku
Wywołuje metodę run()
Ale nie oznacza to, że zostanie od razu uruchomiony - to system zdecyduje kiedy to nastąpi
Stany wątków - nie wykonywany
Wątek przechodzi do tego stanu gdy zachodzi jedno ze zjawisk;
wywołano jego metodę sleepO - uśpienie,
wywołano jego metodę suspemif) - zawieszenie,
wątek wykonuje swoją metodę wait() -oczekiwanie,
wątek jest zablokowany przy operacji wejścia /wyjścia
Stany wątków - nie wykonywany
Powrót do stanu wykonywany gdy zachodzi jedno ze zjawisk:
jeśli uśpiono (metoda sleepf) ), musi upłynąć określona czas,
jeśli zawieszono (metoda suspendO ), inny wątek musi wywołać metodę resumef) ,
jeśli czeka np. na ustawienie jakiejś zmiennej, to obiekt, do którego należy ta zmienna, musi wywołać metodę notify() lub notiJyAll(),
Blokada przez operacje we/wy, operacje te muszą być zakończone
Stany wątków - zakończony
Naturalnie - kończy się metoda run()
public vid run() {
Int i=1;
while (i<51) {
System.out.println( i + „iteracja”);
i++;
}}
Zabity- wywołanie stop()
Thiread mojWatek = new MojaKlasaWatku(); ...
mojWatek.start();
try { Thread.steep(10000); }
catch (InterruptedException e){}
mojWatek.stop();
Priorytety wątków
Priorytety to liczby typu int z zakresu od l do 10
Im większa wartość tym priorytet większy
Priorytet zmieniamy przy pomocy metody setPriorityO
Gdy wątek o większym priorytecie zostaje zatrzymany zostaje wówczas wykonany proces o niższym priorytecie.
Synchronizacja wątków
Synchronizacja konieczne jest gdy dwa wątki wykorzystują wspólne zasoby np. zmienną
Przy dostępie do wspólnych danych nie może być mowy o jednoczesnym i
dowolnym dostępie do zmiennej
Dostęp do zmiennej może mieć tylko jeden wątek.
W programowaniu współbieżnym obszar kodu, który może być wykonywany tylko przez jeden proces nazywamy „sekcja krytyczną"
W Java oznaczenie „sekcji krytycznej" odbywa się przy pomocy słowa kluczowego synchronized.
W Java sekcja krytyczna realizowana jest na poziomie metod.
W Java za realizacje obsługi „sekcji krytycznej" odpowiedzialne są monitory
Monitor jest to twór powiązany z obiektem, który jest rezerwowany w momencie wejścia wątku do sekcji krytycznej i nie pozwala na wejście do sekcji krytycznej innym wątkom
Pozostałe wątki zostaną wstrzymane do momentu opuszczenia SK przez pierwszy wątek i zwolnienia monitora.
Po zwolnieniu monitora kolejne wątki wchodzą do SK i zajmują monitor.
Problemy w synchronizacji
Ponieważ wątki mogą się nawzajem blokować może dochodzić do sytuacji awaryjnych
Zagłodzenia - gdy wątek oczekuje na dostęp do zasobu i nigdy go nie uzyskuje
Zakleszczenie - gdy wątek oczekuje na spełnienie warunku, który nigdy nie będzie spełniony i przez to nigdy nie zwolni sekcji krytycznej
Producent - Konsument
Producent zapisuje dane do Pudełko
Konsument odczytuje dane zPudełko
Pudełko jest to wspólny zasób do którego dostęp trzeba synchronizować
Producent - Konsument
Metoda notifyAll - Informuje wszystkie wątki oczekujące na monitor o fakcie zwolnienia go i budzi wszystkie oczekujące wątki
Metoda wait - Wątek wywołujący tą metodę musi posiadać monitor. Powoduje zwolnienie posiadanego monitora i przejście w stan oczekiwania do momenty gdy inny wątek powiadomi go o zwolnieniu monitora (metoda notify lub notifyAll)