Wykład 8 treść

  1. Wątki

  1. Uruchamianie wątków

Obiekty pozwalają podzielić program na niezależne części. Możliwość pracy wielu wątków pozwala podzielić program na niezależnie działające zadania. Wątki są często nazywane procesami lekkimi. Każdy wątek, podobnie jak proces działa tak, jakby miał procesor do własnej dyspozycji. Procesor jest przydzielany kolejnym wątkom tak jak jest przydzielany kolejnym procesom.

Przejdziemy do omówienia przykładów. Należy pamiętać, że pierwszy wątek powinien zakończyć swoje działanie po zakończeniu wszystkich wątków. W przykładzie, efekt ten został osiągnięty przez zatrzymanie wątku głównego za pomocą metody sleep()

P40Thread.java

W przykładzie powyższym, pętla z metody run() jest przerywana po 6 przejściach. W metodzie main() tworzone są 4 wątki. Tworzony jest obiekt dziedziczący po klasie Thread i wykonywana jest metoda start() tej klasy. Jeden z możliwych wyników, które otrzymamy podczas wykonywania tego programu zamieszczony jest poniżej.

Tworzenie 1

Watek 1(5)

Tworzenie 2

Watek 2(5)

Tworzenie 3

Tworzenie 4

Watek 3(5)

Watek 4(5)

Wątki zostały uruchomione

nrWatku = 1 k= 0

nrWatku = 2 k= 0

nrWatku = 1 k= 1

nrWatku = 3 k= 0

nrWatku = 1 k= 2

nrWatku = 2 k= 1

nrWatku = 4 k= 0

nrWatku = 1 k= 3

nrWatku = 1 k= 4

nrWatku = 3 k= 1

nrWatku = 2 k= 2

nrWatku = 1 k= 5

Watek 1(4)

nrWatku = 1 k= 0

nrWatku = 4 k= 1

nrWatku = 2 k= 3

nrWatku = 1 k= 1

nrWatku = 3 k= 2

nrWatku = 1 k= 2

nrWatku = 2 k= 4

nrWatku = 1 k= 3
nrWatku = 1 k= 4

nrWatku = 4 k= 2

nrWatku = 3 k= 3

nrWatku = 2 k= 5

Watek 2(4)

nrWatku = 1 k= 5

Watek 1(3)

nrWatku = 1 k= 0

nrWatku = 2 k= 0

nrWatku = 1 k= 1

nrWatku = 3 k= 4

nrWatku = 1 k= 2

nrWatku = 4 k= 3

nrWatku = 2 k= 1

nrWatku = 1 k= 3

nrWatku = 1 k= 4

nrWatku = 3 k= 5

Watek 3(4)

nrWatku = 2 k= 2

nrWatku = 1 k= 5

Watek 1(2)

nrWatku = 1 k= 0

nrWatku = 4 k= 4

nrWatku = 2 k= 3

nrWatku = 1 k= 1

nrWatku = 3 k= 0

nrWatku = 1 k= 2

nrWatku = 2 k= 4

nrWatku = 1 k= 3

nrWatku = 1 k= 4
nrWatku = 4 k= 5

Watek 4(4)

nrWatku = 3 k= 1

nrWatku = 2 k= 5

Watek 2(3)

nrWatku = 1 k= 5

Watek 1(1)

nrWatku = 1 k= 0

nrWatku = 2 k= 0

nrWatku = 1 k= 1

nrWatku = 3 k= 2

nrWatku = 1 k= 2

nrWatku = 4 k= 0

nrWatku = 2 k= 1

nrWatku = 1 k= 3

nrWatku = 1 k= 4

nrWatku = 3 k= 3

nrWatku = 2 k= 2

nrWatku = 1 k= 5

Koniec wątku 1

nrWatku = 4 k= 1

nrWatku = 2 k= 3

nrWatku = 3 k= 4

nrWatku = 2 k= 4

nrWatku = 4 k= 2

nrWatku = 3 k= 5

Watek 3(3)

nrWatku = 2 k= 5

Watek 2(2)

nrWatku = 2 k= 0
nrWatku = 3 k= 0

nrWatku = 4 k= 3

nrWatku = 2 k= 1

nrWatku = 3 k= 1

nrWatku = 2 k= 2

nrWatku = 4 k= 4

nrWatku = 2 k= 3
nrWatku = 3 k= 2

nrWatku = 2 k= 4

nrWatku = 4 k= 5

Watek 4(3)

nrWatku = 3 k= 3

nrWatku = 2 k= 5

Watek 2(1)

nrWatku = 2 k= 0

nrWatku = 3 k= 4

nrWatku = 4 k= 0

nrWatku = 2 k= 1

nrWatku = 3 k= 5

Watek 3(2)

nrWatku = 2 k= 2

nrWatku = 4 k= 1

nrWatku = 2 k= 3

nrWatku = 3 k= 0

nrWatku = 2 k= 4

nrWatku = 4 k= 2

nrWatku = 3 k= 1

nrWatku = 2 k= 5

Koniec wątku 2

nrWatku = 3 k= 2
nrWatku = 4 k= 3

nrWatku = 3 k= 3

nrWatku = 4 k= 4

nrWatku = 3 k= 4

nrWatku = 4 k= 5

Watek 4(2)

nrWatku = 3 k= 5

Watek 3(1)

nrWatku = 3 k= 0

nrWatku = 4 k= 0

nrWatku = 3 k= 1

nrWatku = 4 k= 1

nrWatku = 3 k= 2

nrWatku = 4 k= 2

nrWatku = 3 k= 3

nrWatku = 3 k= 4

nrWatku = 4 k= 3

nrWatku = 3 k= 5

Koniec wątku 3

nrWatku = 4 k= 4

nrWatku = 4 k= 5

Watek 4(1)

nrWatku = 4 k= 0

nrWatku = 4 k= 1

nrWatku = 4 k= 2

nrWatku = 4 k= 3

nrWatku = 4 k= 4

nrWatku = 4 k= 5

Koniec wątku 4

Koniec wątku głównego

  1. Klasy wewnętrzne i wątki

W następnym przykładzie stworzone są dwie wewnętrzne klasy wątku. Klasy wewnętrzne mogą działać na zmiennych klasy zewnętrznej(otaczającej). Zarówno statycznych jak i niestatycznych. Klasy wewnętrzne nie mogą posiadać zmiennych statycznych. Pierwszy z wątków jest uruchamiany jeden raz drugi jest uruchamiany dwukrotnie. Wyniki działania są umieszczone poniżej. A oto ten przykład.

P41Thread.java

A 1 pozostalo 5 s = 0

Wątki zostaly uruchomione

B 2 pozostalo 3 s = 1

B 3 pozostalo 3 s = 2

A 1 k = 0

B 2 k = 0 Sat May 18 09:02:45 CEST 2013

A 1 k = 1

A 1 pozostalo 4 s = 3

B 3 k = 0 Sat May 18 09:02:50 CEST 2013

A 1 k = 0

B 2 k = 1 Sat May 18 09:02:55 CEST 2013

A 1 k = 1
A 1 pozostalo 3 s = 4

A 1 k = 0

B 3 k = 1 Sat May 18 09:03:05 CEST 2013

B 2 k = 2 Sat May 18 09:03:05 CEST 2013

B 2 pozostalo 2 s = 5
A 1 k = 1

A 1 pozostalo 2 s = 6

B 2 k = 0 Sat May 18 09:03:15 CEST 2013

A 1 k = 0
B 3 k = 2 Sat May 18 09:03:20 CEST 2013

B 3 pozostalo 2 s = 7

A 1 k = 1

A 1 pozostalo 1 s = 8

B 2 k = 1 Sat May 18 09:03:25 CEST 2013

A 1 k = 0

A 1 k = 1

Koniec A 1

B 3 k = 0 Sat May 18 09:03:35 CEST 2013

B 2 k = 2 Sat May 18 09:03:35 CEST 2013

B 2 pozostalo 1 s = 9
B 2 k = 0 Sat May 18
09:03:45 CEST 2013

B 3 k = 1 Sat May 18 09:03:50 CEST 2013

B 2 k = 1 Sat May 18 09:03:55 CEST 2013

B 3 k = 2 Sat May 18 09:04:05 CEST 2013

B 3 pozostalo 1 s = 10

B 2 k = 2 Sat May 18 09:04:05 CEST 2013

Koniec B 2

B 3 k = 0 Sat May 18 09:04:20 CEST 2013

B 3 k = 1 Sat May 18 09:04:35 CEST 2013

B 3 k = 2 Sat May 18 09:04:50 CEST 2013

Koniec B 3

Koniec wątku głównego

  1. Interfejs Runnable

Następny przykład jest analogiczny do pierwszego spośród przykładów dotyczących wątków. W tym przykładzie wątki są zbudowane przez implementację interfesu Runnable.

P42Thread.java

Tworzenie 1

Tworzenie 2

Watek 1(5)

Tworzenie 3

Tworzenie 4

Watek 3(5)

Wątki zostały uruchomione

Watek 2(5)

Watek 4(5)

nrWatku = 1 k= 0

nrWatku = 1 k= 1

nrWatku = 2 k= 0

nrWatku = 1 k= 2

nrWatku = 3 k= 0

nrWatku = 1 k= 3

nrWatku = 4 k= 0

nrWatku = 2 k= 1

nrWatku = 1 k= 4

nrWatku = 1 k= 5
Watek 1(4)

nrWatku = 3 k= 1

nrWatku = 2 k= 2

nrWatku = 1 k= 0

nrWatku = 1 k= 1

nrWatku = 4 k= 1
nrWatku = 2 k= 3

nrWatku = 1 k= 2

nrWatku = 3 k= 2

nrWatku = 1 k= 3

nrWatku = 2 k= 4

nrWatku = 1 k= 4

nrWatku = 1 k= 5
Watek 1(3)

nrWatku = 3 k= 3

nrWatku = 4 k= 2

nrWatku = 2 k= 5

Watek 2(4)

nrWatku = 1 k= 0

nrWatku = 1 k= 1

nrWatku = 2 k= 0

nrWatku = 1 k= 2

nrWatku = 3 k= 4

nrWatku = 1 k= 3

nrWatku = 4 k= 3

nrWatku = 2 k= 1

nrWatku = 1 k= 4

nrWatku = 1 k= 5

Watek 1(2)

nrWatku = 3 k= 5

Watek 3(4)
nrWatku = 2 k= 2

nrWatku = 1 k= 0

nrWatku = 1 k= 1

nrWatku = 4 k= 4

nrWatku = 2 k= 3

nrWatku = 1 k= 2

nrWatku = 3 k= 0

nrWatku = 1 k= 3
nrWatku = 2 k= 4

nrWatku = 1 k= 4

nrWatku = 1 k= 5

Watek 1(1)

nrWatku = 3 k= 1

nrWatku = 4 k= 5

Watek 4(4)

nrWatku = 2 k= 5

Watek 2(3)

nrWatku = 1 k= 0

nrWatku = 1 k= 1

nrWatku = 2 k= 0

nrWatku = 1 k= 2

nrWatku = 3 k= 2

nrWatku = 1 k= 3

nrWatku = 4 k= 0

nrWatku = 2 k= 1

nrWatku = 1 k= 4

nrWatku = 1 k= 5

nrWatku = 3 k= 3

nrWatku = 2 k= 2

nrWatku = 4 k= 1

nrWatku = 2 k= 3

nrWatku = 3 k= 4

nrWatku = 2 k= 4

nrWatku = 3 k= 5

Watek 3(3)
nrWatku = 4 k= 2

nrWatku = 2 k= 5

Watek 2(2)

nrWatku = 2 k= 0

nrWatku = 3 k= 0

nrWatku = 4 k= 3

nrWatku = 2 k= 1

nrWatku = 3 k= 1

nrWatku = 2 k= 2

nrWatku = 4 k= 4

nrWatku = 2 k= 3

nrWatku = 3 k= 2

nrWatku = 2 k= 4

nrWatku = 3 k= 3

nrWatku = 4 k= 5

Watek 4(3)

nrWatku = 2 k= 5

Watek 2(1)

nrWatku = 2 k= 0

nrWatku = 3 k= 4

nrWatku = 4 k= 0

nrWatku = 2 k= 1

nrWatku = 3 k= 5

Watek 3(2)

nrWatku = 2 k= 2

nrWatku = 4 k= 1

nrWatku = 2 k= 3

nrWatku = 3 k= 0

nrWatku = 2 k= 4

nrWatku = 3 k= 1

nrWatku = 4 k= 2

nrWatku = 2 k= 5

nrWatku = 3 k= 2

nrWatku = 4 k= 3

nrWatku = 3 k= 3

nrWatku = 4 k= 4

nrWatku = 3 k= 4

nrWatku = 3 k= 5

Watek 3(1)

nrWatku = 4 k= 5

Watek 4(2)

nrWatku = 3 k= 0

nrWatku = 4 k= 0

nrWatku = 3 k= 1

nrWatku = 4 k= 1

nrWatku = 3 k= 2

nrWatku = 3 k= 3

nrWatku = 4 k= 2

nrWatku = 3 k= 4

nrWatku = 4 k= 3

nrWatku = 3 k= 5

nrWatku = 4 k= 4

nrWatku = 4 k= 5

Watek 4(1)
nrWatku = 4 k= 0

nrWatku = 4 k= 1

nrWatku = 4 k= 2

nrWatku = 4 k= 3

nrWatku = 4 k= 4

nrWatku = 4 k= 5

Koniec wątku głównego

  1. Wykorzystanie metod klasy Thread

W przykładzie następnym oczekiwanie na zamknięcie wszystkich wątków jest wykonane przez wywołanie metody join() dla każdego z wątków.

P43Thread.java

  1. Priorytety

W następnym przykładzie prześledzimy działanie priorytetów. Program ten może różnie działać, w różnych systemach operacyjnych. Jest to zależne od sposobu traktowania wątków. Mimo ustawienia priorytetów może się zdarzyć, że jeden z wątków zawłaszczy procesor. Dobrą metodą na uzyskanie płynności pracy wątków jest dobrowolne oddawanie sterowania do procesora. Program uruchamia 3 wątki, główny i dwa potomne. Wątki potomne powiększają wartość jednej zmiennej o jeden. Wątek główny jest usypiany na pewien czas, tak więc dwa wątki potomne rywalizują wyłącznie ze sobą i pozostałymi zadaniami systemu (na to nie mamy wpływu). Wyniki uzyskiwane świadczą o tym, że w tym systemie, następuje przełączanie kontekstu bez konieczności zaprogramowania oddawania sterowania do procesora. Słowo kluczowe volatile powoduje, że pętla ze zmienną petla nie będzie optymalizowana.

P44Thread.java

Priorytet może się zmieniać (obecnie) od 1-10, czyli od Thread.MIN_PRIORITY, przez Thread.NORM_PRIORITY do Thread.MAX_PRIORITY. Wyniki uzyskane w tym programie świadczą o tym, że wątki są wykonywane w sposób płynny, jeśli czas przydzielany poszczególnym watkom jest przyznawany w odpowiednio długi czasie.

  1. Synchronizacja wątków

Wątki mogą korzystać ze wspólnych danych, często wymaga to synchronizacji. W Javie synchronizacja jest dostępna na poziomie języka. Podstawowym pojęciem związanym z synchronizacją jest monitor (semafor). Monitor to obiekt, który zakłada blokadę wzajemnie wykluczającą. Gdy wątek założy blokadę (wchodzi do monitora), wszystkie inne wątki, które chcą wejść do monitora będą musiały czekać. Synchronizacja w Javie sprowadza się do wywołania metody z modyfikatorem synchronized. Jeśli jeden wątek zacznie wykonywać metodę synchronizowaną wtedy pozostałe wątki, które chcą wykonać tę lub inną metodę synchronizowaną dla tego samego obiektu muszą czekać. Przyjrzyjmy się programowi, który wyprowadza na ekran tekst w nawiasach. W poniższym programie metoda drukuj() wykonywana jest w metodzie run() i uruchamiane są trzy wątki. W metodzie drukuj() oddawane jest sterowanie do procesora i wydruki z różnych wątków przeplatają się.

P45Thread.java

Metoda drukująca powinna być metodą synchronizowaną.

P46Thread.java

Synchronizowanie metody drukuj() z klasy DrukA jest możliwe, gdy mamy dostęp do źródła klasy zawierającej. Jeśli jest to niemożliwe, to można zapewnić synchronizowany dostęp do obiektu tej klasy. Program może mieć poniższą postać.

P47Thread.java

  1. Komunikacja międzywątkowa

Synchronizowane metody blokują dostęp dla innych wątków w sposób bezwzględny. Klasyczny problem konsument - producent, przy założeniu, że konsument pobiera dane gdy producent je wyprodukuje, i na odwrót. Do realizacji tego zadania potrzebne będą metody służące komunikacji międzywątkowej. Metody te pochodzą z klasy Object i są to metody:

Poniższy program realizuje zadanie producent - konsument. Program zapisany jest za pomocą czterech. Klasa Kolejka będzie zawierała metody pozwalające na ustawienie wyprodukowanej liczby (produkt) i jej pobranie, metody te muszą być zsynchronizowane. Ponadto należy zadbać o to, by żadna wyprodukowana liczba nie była pobrana wielokrotnie i by wyprodukowana liczba nie była pominięta.

Klasy Producet i Konsument będą klasami budującymi wątki korzystające Wcześniej zbudowane metody z klasy Kolejka. Konsument będzie pobierał z kolejki, producent będzie wstawiał do kolejki. Jeśli zostaną usunięte linie z komentarzami umieszczonymi po instrukcjach, wtedy nie uzyskamy, mimo synchronizacji tego samego efektu. Będzie możliwe produkowanie wielu liczb bez pobierania i na odwrót.

P48Thread.java

Istnieje możliwość blokady wzajemnej. Wystarczy sobie wyobrazić wątek X wchodzący do monitora obiektu X i inny wątek wchodzący do monitora obiektu Y. Wątek z obiektu X próbuje wykonać metodę synchronizowaną obiektu Y, wątek ten zostanie zablokowany. Wątek z obiektu Y spróbuje wykonać dowolną metodę synchronizowaną obiektu X, czas oczekiwania na wykonanie tej metody będzie nieskończony. Dostanie się do obiektu X wymaga zwolnienia blokady z Y.

Wzajemna blokada jest błędem bardzo trudnym do wykrycia. Wzajemna blokada jest dość rzadko spotykana, czas wykonania dwóch lub więcej wątków muszą ułożyć się w odpowiedni sposób. Blokada wzajemna może dotyczyć więcej niż dwóch wątków i synchronizowanych obiektów. Poniższy przykład pokazuje wzajemną blokadę wątków. Metody metodaRazB() i metodaDwaB() nie mają szansy na wykonanie.

P49Thread.java

  1. Zawieszanie wątków, wznawianie wątków, zatrzymywanie wątków

We wczesnych wersjach Javy do sterowania wątkami, a więc do zawieszania wznawiania i zatrzymywania wątków służyły metody: suspend(), resume(), stop(). Metoda suspend() powodowała czasem błędy systemowe. Zdarzało się, że wątek dostawał blokadę na dostęp do danych, zatrzymanie takiego wątku nie zwalniało blokady i pozostałe wątki oczekujące na dostęp do danych mogły doprowadzić blokady wzajemnej. Metody (resume() bez suspend() nie ma sensu) te obecnie uważane są za przestarzałe, wręcz nie należy ich używać.

Obecnie do tego typu sterowania używane są odpowiednie flagi, których wartości są ustawiane na wartość true lub false i mogą być warunkiem wywołania metody wait() lub notify().

Ten sam tryb można zastosować do zatrzymywania wątków

Ilustracją takiego postępowania jest poniższy program. Mimo, że takie wstrzymywanie i wznawianie wątków wydaje się być mniej eleganckie niż użycie metod suspend(), resume(), należy stosować właśnie takie podejście.

P50Thread.java


Wyszukiwarka

Podobne podstrony:
Wykład 4 treść
Wykład 1 treść
Wykład 6 treść
Wykład 3 treść
EPGMIPG mini WYKLADY tresc
Wykład 5 treść
wykład 4 Treść kształcenia
Wykład (treść biologia komórki) - biologia, I rok, II semestr, biologia komórki, Wojtek, Biologia ko
PC wyklad tresc
Wykład 2 treść
Wykład 7 treść
TRESC WYKLADU
2 Tresc zakres folia, Wykłady
fiz zagadnienia na egzamin u pekaly , TREŚĆ WYKŁADU
wykład-alg SP-treść, ZiIP Politechnika Poznańska, Badania Operacyjne
Treść programowa COWIG sem 7 OIE wykład& 11
badania fizykalne treść wykładu, Badania fizykalne
wykłady dr Springer treść wykładów najważniejsze my

więcej podobnych podstron