[ Pobierz całość w formacie PDF ]
.currentTimeMillis();wait(200);if ((System.currentTimeMillis() - zwloka) > 200) {System.out.println("Tu "+kto+", czekam na ruch osobnika:"+ strzelec);4-14Jacek Rumiński - Język JAVA Jacek Rumiński - Język JAVA Rozdział 4Jacek Rumiński - Język JAVA Jacek Rumiński - Język JAVA }} catch (InterruptedException ie) {}}return true;}}//koniec class Strzalclass Strzelec implements Runnable {Strzal s;String wrogPubliczny;public Strzelec(String wrog, Strzal st) {s = st;wrogPubliczny = wrog;}public void run() {while (s.strzal(wrogPubliczny)) ;}}// koniec class Strzelecpublic class Wojna {public static void main(String args[]) {Strzal st = new Strzal();Thread luke = new Thread(new Strzelec("Vader", st));Thread vader = new Thread(new Strzelec("Luke",st));luke.setName("Luke");vader.setName("Vader");luke.start();vader.start();try {Thread.currentThread().sleep(1000);} catch (InterruptedException ie) {}st.strzal("POKOJ");System.out.println("Nastał pokój!!!");}}// koniec public class WojnaPrzykładowy program skonstruowano z trzech klas.Pierwsza z nich jestodpowiedzialna za wysyłanie komunikatów w zależności od podanej nazwy zmiennej.Jeżeli nazwa strzelca jest inna niż bieżąca (czyli inna niż tego do kogo należy ruch)to następuje oczekiwanie na nowego strzelca.Druga klasa tworzy definicję metodyrun() konieczną dla opisania działania wątków.Ostatnia główna klasa programutworzy obiekt klasy opisującej proces strzelania (klasy pierwszej) a następnieuruchamia dwa wątki podając nazwy wrogich strzelców względem danego wątku.Strzelanie trwa jedną sekundę po czym następuje POKOJ , czyli przerwanie pracywątków poprzez zakończenie pracy metod run() (w pętli while() pojawia się wartośćlogiczna false).Efektem działania programu jest następujący wydruk:4-15Jacek Rumiński - Język JAVA Jacek Rumiński - Język JAVA Rozdział 4Jacek Rumiński - Język JAVA Jacek Rumiński - Język JAVA PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)PIF! (Luke)PAF! (Vader)Nastał pokój!!!Warto wspomnieć coś na temat stanów wątku.Do podstawowych należy zaliczyć teopisywane przez metody isAlive() oraz isInterrupted().Metoda isAlive() zwracawartość logiczną true jeżeli dany wątek został uruchomiony (start()) i nie zostałjeszcze zakończony (nie umarł).Metoda isAlive() nie dostarcza informacji o tym, czywykonywanie danego wątku jest zawieszone tymczasowo czy nie (brak rozróżnieniapomiędzy wątkiem Runnable i Not Runnable).Metoda isInterrupted() zwraca wartośćtrue jeżeli dla danego wątku została przesłana wiadomość (wykonano metodę)interrupt().4.7 Synchronizowanie wątkówJeśli dwa wątki konkurują w celu uzyskania praw dostępu do danego obiektuto zachowanie kodu zależeć może od tego, który wątek wygra.Zjawisko te (racecondition - wyścig) jest najczęściej bardzo niekorzystne ze względu na brak kontroli(nieokreśloność) w zapewnianiu kolejności obsługi wiadomości generowanych przezróżne wątki do tego samego obiektu.Załóżmy, że istnieje następująca klasa:cllass Testt{{class Test{c ass Tesiintt n=0;;int n=0;n n=04-16Jacek Rumiński - Język JAVA Jacek Rumiński - Język JAVA Rozdział 4Jacek Rumiński - Język JAVA Jacek Rumiński - Język JAVA iintt m=1;;int m=1;n m=1voiid zamiianaLP(()){{void zamianaLP(){vo d zam anaLPn=m;;n=m;n=m}}}voiid zamiianaPL(()){{void zamianaPL(){vo d zam anaPLm=n;;m=n;m=n}}}}}//// koniiec cllass Testt}// koniec class Testkon ec ca ss Tesoraz stworzone są dwa wątki, jeden wykonuje metodę zamianaLP(), drugi wykonujemetodę zamianaPL().O ile oba wątki są równouprawnione i wykonywane sąrównolegle, to problem polega na określeniu kolejności działania, czyli określeniujakie wartości końcowe przyjmą pola n i m.obiektu klasy Test.Możliwe są tu różnesytuacje.Każda z dwóch metod wykonuje dla swoich potrzeb aktualne kopie roboczezmiennych.Następnie po wykonaniu zadania wartości tych zmiennych sąprzypisywane do zmiennych oryginalnych przechowywanych w pamięci głównej.Jakłatwo się domyśleć możliwe są więc następujące stany końcowe zmiennych:- n=0,m=0; wartość zmiennej n została przepisana do m;- n=1, m=1; wartość zmiennej m została przepisana do n;- n=1, m=0; wartości zmiennych zostały zamienione.W większości przypadków (poza generatorem pseudolosowym) zjawisko wyścigujest niekorzystne.Konieczne jest więc zastosowanie takiej konstrukcji kodu abymożna było to zjawisko wyeliminować.Zanim jednak zaprezentowane zostanierozwiązanie problemu warto przeanalizować konkretny przykład.Przykład 4.5://WyscigiNN.java:public class WyscigiNN implements Runnable{private int n;WyscigiNN(int nr){this.n=nr;}void wyswietl(int i){System.out.println("Dobro = "+i);System.out.println("Zlo = "+i);}void zmianaZla(){System.out.print("ZLO: ");for(int l=0; l
[ Pobierz całość w formacie PDF ]