Temat: Wątki
Czym są wątki. Grafika. Proste animacje. Małe podsumowanie materiału.
Czym są wątki. Grafika. Proste animacje. Małe podsumowanie materiału.
Na podstawie: Arnold, Gosling; Boone; Eckel.
1 Wątki
Zwykłe operacje w programach komputerowych są wykonywane sekwencyjnie, tzn. kolejno, jedna po drugiej. Są to tzw. programy jednowątkowe. JavaTM stwarza możliwość wykonywania programu wielowątkowo. Wątki mogą przy tym korzystać i modyfikować te same zasoby danych. Wymaga to koordynacji przebiegu poszczególnych wątków. Wątki nie mogą przeszkadzać sobie nawzajem i dostęp do zasobów przez poszczególne wątki nie powinien odbywać się chaotycznie. Mechanizmy obsługi wątków są w JavaTM wysoko wyspecjalizowane. Są to blakady zasobów, odpytywanie itp.2 Tworzenie wątków
Wątki w JavaTM udostępnia klasa Thread. Wątek tworzymy poleceniem - Thread przebieg = new Thread();
Następnym krokiem jest konfiguracja utworzonego wątku.
Można go nazwać, nadać mu priorytet początkowy i następnie
wykonać uruchamiając metodę start() wątku. Tak uruchomiony
wątek wykonuje następnie metodę run(). Po wykonaniu tej
metody wątek ginie. Wątek można też zatrzymać uruchamiając metodę
stop() wątku. Metoda sleep(milis) usypia wątek
na milis milisekund.
Poniższy przykład pochodzi z podręcznika Arnolda i Goslinga,
JavaTM
.
// // K. Arnold, J. Gosling, Java // PingPong.class; // Wątki // class PingPong extends Thread { String word;// co wypisać int delay; PingPong(String whatToSay, int delayTime) { word = whatToSay; delay = delayTime; } public void run() { try { for (;;) { System.out.print(word + " "); sleep(delay); // czekaj na nastepna kolejke } } catch (InterruptedException e) { return; // zakoncz ten watek } } public static void main(String[] args) { new PingPong("ping", 33).start(); // 1/30 sec new PingPong("PONG",100).start(); // 1/100 sec } }(Program do pobrania: jpgm/PingPong) Klasa PingPong jest potomkiem klasy Thread. Konstruktor obiektów tej klasy ustawia dwie zmienne. Jedna z nich to word, zawierająca dowolny napis (tutaj ping lub PONG), a druga jest czasem który wątek przesypia, a więc jest nieaktywny. Metoda main deklaruje dwa wątki i uruchamia je. Jeden z nich (ping) budzi się co 33/1000 ms, a drugi (PONG) co 1/10 ms. Pilnuje tego metoda run() wątku, która zatrzymuje go na ten czas wywołując metodę sleep(delay) z parametrem delay, określającym liczbę przesypianych milisekund. Wynik programu będzie podobny do następujacego.
ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping PONG ping ping ping PONG ping ping PONG ping ping PONG ping ping PONG ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONG ping ping ping PONGWidzimy, że napisy ping i PONG różnią się częstością występowania. Metoda setName nadaje nazwę wątkowi, a getName odczytuje ją. Nazwą można też nadać przekazując konstruktorowi wątku obiekt klasy String.
3 Synchronizacja
Metody JavaTM mogą być synchronizowane (synchronized). Jeśli jakiś wątek wykonuje taką metodę dla danego obiektu, to wchodzi jednocześnie do tzw. monitora obiektu i wszystkie inne wywołania metod synchronizowanych dla tego obiektu muszą czekać, aż wątek opuści monitor. Dzieje się to wtedy gdy metoda synchronizowana zakończy się. Synchronizacja wymusza wzajemne wykluczanie wykonywania sie wątków w tym samym czasie.
P r z y k ł a d 1.
Poniższa metoda zamienia wszystkie elementy tablicy na dodatnie,
zastępując wszystkie ujemne elementy ich wartością bezwzględną.
Fragment tej metody musimy synchronizować po to, by żaden
inny wątek oprócz wątku aktualnie wywołującego metode nie mógł
przypadkowo zmienić już zmienionych danych.
Dwie metody wait i notify, zdefiniowane w klasie
Object, pozwalaja na dodatkową
komunikację między wątkami. Metoda wait każe wątkowi
czekać, aż jakieś wydarzenie zostanie zrealizowane, a metoda
notify informuje o tym fakcie.
Schemat, wg. którego stosuje się metodę wait pokazany
jest niżej.
// zamień wszystkie elementy tablicy na nieujemne // Arnold, Gosling public static void abs(int[] values) { synchronixed (values) { for(int i = 0; i < values.length; i++) { if(values[i] < 0) values[i] = -values[i]; } } }Operacje na elementach tablicy są synchronizowane. Dopiero po wykonaniu całej pętli obiekt zajęty przez wątek zostaje zwolniony. Mamy pewność, że cała tablica została przebadana i żaden inny przypadkowy proces nie zmienił jej zawartości.
synchronized void wykonajWarunkowo() { while( !warunek) wait(); ... kod do wykonania po spełnieniu warunku }Nie będziemy tu omawiać problemów tzw. zakleszczania wątków, licząc na to, że nasze programy nie będą zbyt złożone.
4 Dodatki
Wątki można zawieszac (suspend). Jest to przydatne gdy chcemy by działały one w pewnych tylko chwilach, a więc wtedy, gdy potrzeba. Elegancki sposób zatrzymywania wątku polega nie na jego przerwaniu metodą stop, lecz inaczej. Zazwyczaj w metodzie run sprawdza się jakąś zmienna logiczną, której wartość może się zmieniać w zależności od warunków.5 Algorytmy sortowania
Klasycznym już przykładem ilustrującym trzy algorytmy sortowania, zrealizowanym w JavaTM pokazana w ilustracjach dystrybucji Java SDK 2. (patrz jdk1.3//demo//applets//SortDemo).The Sorting Algorithm Demo (1.1)
Bi-Directional Bubble Sort Bubble Sort Quick Sort
The Sources
The applet.The "generic" sorting algorithm.
The Bi-directional Bubble Sort algorithm.
The Bubble Sort algorithm.
The Quick Sort algorithm.
6 Klasa Runnable
Oprócz klas, JavaTM dostarcza tzw. interfejsów (sprzęg). Interfejs stanowi typ składający sie tylko z metod abstrakcyjnych oraz stałych. Interfejs jest przykładem czystej formy projektu, klasy zaś są mieszanką projektu i implementacji (Arnold, Gosling). Klasy mogą implementować metody interfejsu tak, jak chce programista. W ten sposób interfejs ma dużo więcej możliwych implementacji niż klasa. Klasa może implementowac wiele interfejsów naraz. Jednym z interfejsów JavaTM jest Runnable. Runnable deklaruje jedną metodę: - public void run();
Oto jak wyglada program PingPong (teraz RunPingPong), gdzie
zastosowano interfejs Runnable.
// // K. Arnold, J. Gosling, Java // PingPong.class; // Wątki // class RunPingPong implements Runnable { String word;// co wypisać int delay; // ile czekać RunPingPong(String whatToSay, int delayTime) { word = whatToSay; delay = delayTime; } public void run() { try { for (;;) { System.out.print(word + " "); sleep(delay); // czekaj na nastepna kolejke } } catch (InterruptedException e) { return; // zakoncz ten watek } } public static void main(String[] args) { Runnable ping = new RunPingPong("ping", 33); Runnable pong = new RunPingPong("PONG",100); new Thread(ping).start(); new Thread(pong).start(); } }(Program do pobrania: jpgm/RunPingPong) Tworzone obiekty (ping i pong) klasy Thread są uruchamiane poprzez wywołanie metody start(). Wynik działania programu jest podobny do poprzedniego.
7 Pewne uzupełnienia
Podamy kilka konstrukcji JavaTM , znanych (lub podobnych) do odpowiednich konstrukcji programistycznych C++ lu Pascala.7.1 Przepływ sterowania
if (boolean) instrukcja else instrukcja switch(zmienna) { case wartość: instrukcja case wartość: instrukcja ... default: instrukcja } break [etykieta] continue [etykieta] return [wartość] for([wartość_początkowa];[warunek_zakończenia];[wartość_końcowa]) [instrukcja] while (boolean) instrukcja do instrukcja while (boolean) etykieta: instrukcja boolean ? wynik_gdy_prawda : wynik_gdy_fałsz
7.2 Układacze
Aplet lub okno można wyposażyć w różne elementy, jak przyciski (Button), pola tekstowe (TextField), etykiety (Label) itd. Układamy je w pojemnikach. W JavaTM czynią to specjalne układacze. Są toFlowLayout - standardowy ukladach w apletach BorderLayout CardLayout GridLayout GridBagLayoutFlowLayout. Dodaje elementy do pojemnika od lewej strony do prawej, wyśrodkowując każdy z nich w pionie. Ułożeniem sterują parametry: LEFT, CENTER, RIGHT. BorderLayout. Umieszcza elementy w pozycjach North, South, West, East i Center.
| ... | setLayout(new BorderLayout()); // wybierz układacz | resize(400, 200); // ustaw rozmiar okna | textF = new TextField(6); | add("North", textF); | label = new Label("Etykieta"); | add("South", label); | ...GridLayout. Elementy umieszczane są w siatce o jednakowych oczkach, kolejno od lewej strony do prawej.
| setLayout(new GridLayout(1,2)); +------------------------------+ | | element| | element | | +------------------------------+ | setLayout(new GridLayout(2,1)); +---------------+ | | element| | | | | | element| | +---------------+W tym miejscu nie będziemy mówić o słuchaczach oraz adapterach. Wyposaża się w nie elementy by reagowały na zdarzenia takie jak np. ruch myszki, naciśnięcie przycisku myszy, naciśnięcie klawisza i setki innych.
Z a d a n i e 1.
Należy przeczytać,
np. w www.javasoft.com [ http://www.javasoft.com ]
o elementach graficznych (TextField, Label, CheckBox, RadioButton,
DropDownList) oraz o starych metodach obsługi zdarzeń (action(),
handleEvent(), actionListener(), ...) i nowych odpowiednikach
w JDK 2.
P r z y k ł a d 2.
Procedura handleEvent().
... Button b1 = new Button("Guzik1"); Button b2 = new Button("Guzik2"); ... public boolean action(Event e, Object o) { if(e.target.equals(b1)) getAppletContext().showStatus("Guzik 1"); else if(e.target.equals(b2)) getAppletContents().showStatus("Guzik 2"); else return super.action(e, arg); return true; }
8 Małe podsumowanie
Na podstawie: Boone
Zbierzemy najważniejsze informacje o JavaTM . Jeśli czegoś nie rozumiesz, szukaj w podręcznikach.8.1 Definicje klas
- interface definiuje dane globalne i sygnatury metod, które mogą być wspólne dla wielu klas
- classs definiuje zespół danych i metod
- extends wskazuje klasę nadrzędną
- implements wskazuje nazwę interfejsu, którego metody dana klasa realizuje
8.2 Słowa kluczowe dla klas i zmiennych
- abstract informuje, że nie można tworzyć obiektów danej klasy
- public klasa, metoda lub zmienna jest dostępna wszędzie
- private oznacza, że tylko w klasie definiującej można używać zmiennej
- protected tylko klasa definiujące i jej podklasy mogą używać zmiennej
- static oznacza, że zmienna (metoda) jest związana z klasą, a nie z konkretnym obiektem danej klasy
- synchronized tylko jeden obiekt lub klasa może korzystać z zaznaczonej tak zmiennej
- volatile informuje, że wartość zmiennej może być zmieniona przez inny wątek
- final zmienna lub metoda nie może zostac zmieniona przez klasy poczodne
- native związanie metody z kodem dla danego procesora
8.3 Typy proste
- long (64b)
- int (32b)
- short (16b)
- byte (8b)
- char (16b, UNICODE)
- doule (64b)
- float (32b)
- boolean (true, false)
- void
8.4 Wartości i zmienne
- false
- true
- this odnosi się do obiektu bieżącego w metodzie danego obiektu
- super odnosi się do bezpośredniej nadklasy w metodzie danego obiektu
- null oznacza nie istniejący obiekt
8.5 Wyjątki
- throw zgłasza wyjątek
- try zaznacza pozycję (na stosie), do której można się wycofać
- catch przechwytuje wyjątek
- finally wskazuje blok, który należy wykonać niezależnie od zgłoszonych wyjątków
8.6 Tworzenie obiektów i sprawdzanie
- new tworzy nowy obiekt
- instanceOf sprawdza czy wymieniony obiekt jest potomkiem wymienionej klasy lub interfejsu
8.7 Sterowanie
- switch sprawdza wartość zmiennej
- case wykonuje blok w zależności od wartości zmiennej
- default oznacza blok, który należy wykonać jeśli w instrukcji switch brakuje odpowiedniego bloku case
- break przerywa wykonanie bloku
- continue przejście do następnej iteracji pętli
- do wykonuje instrukcję
- if sprawdza warunek i wykonuje instrukcję lub nie
- else jeśli warunek jest false wykonuje instrukcje
- for organizuje pętle
- while pętla warunkowa
- return powrót z metody i ewentualne przekazanie wartości