background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 1 

6. W

ą

tki 

 
 
 

6.1 Poj

ę

cie w

ą

tku programu 

6.2 Klasy 

Timer

TimerTask

 

6.3 Klasa 

Thread

 

6.4 Synchronizacja pracy w

ą

tków 

6.5 Grupowanie w

ą

tków 

 
 
 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 2 

 

6.1 W

ą

tki programu 

1) Poj

ę

cie w

ą

tku 

W

ą

tek  ("thread")

  to  osobna  sekwencja  wykonania  instrukcji  programu 

w  ramach  jednego  programu,  wykonywana 

współbie

Ŝ

nie

  z  innymi 

w

ą

tkami tego programu.  

W  odró

Ŝ

nieniu  od  procesu  w

ą

tek  posiada  jedynie  swój 

kontekst 

wykonania  –  stos,  rejestry  i  licznik  rozkazów

  –  ale  współdzieli  on 

pami

ęć

  dynamiczn

ą

  („stert

ę

”)  programu  z  innymi  w

ą

tkami  tego 

programu. 
W

ą

tki  znajduj

ą

  zastosowanie  tam,  gdzie  rozwi

ą

zanie  zadania  mo

Ŝ

by

ć

  zrealizowane  przez 

algorytm  równoległy

.  Przykłady  zada

ń

  dla 

w

ą

tków: obliczenie liczb pierwszych, sortowanie danych, wykonywanie 

animacji, itp. 
Dzi

ę

ki 

w

ą

tkom 

realizujemy 

mechanizm 

asynchronicznego 

wywoływania i wykonywania metod w

 ramach jednego programu. 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 3 

6.2 Klasy 

Timer

 i 

TimerTask 

 

Klasy 

java.util.Timer

 

(

extends  Object

)

  i 

TimerTask

 

(extends  Object 

implements Runnable)

 

s

ą

 po

Ŝ

yteczne do wyznaczania czasu wznowienia 

w

ą

tku po pewnej przerwie. 

Uwaga:  dla  programu  posiadaj

ą

cego  GUI  realizowany  w 

Swing

-u 

odpowiedni

ą

 klas

ą

 jest 

javax.swing.Timer

 zamiast 

java.util.Timer

.  

Metody klasy 

Timer

 przeznaczone do 

wybierania zada

ń

:  

// Wykonanie zadania po upływie czasu lub o dokładnej porze: 

schedule (TimerTask task, long delay)

  

schedule (TimerTask task, Date time)

  

// Wielokrotne wznawianie wykonania co okres czasu: 
// - "mi

ę

kkie" dotrzymanie okresu – gdy poprzednie wykonanie si

ę

 zako

ń

czyło 

schedule (TimerTask task, long delay, long okres)

  

schedule (TimerTask task, Date time, long okres)

  

//- ustalony na sztywno okres –bez wzgl

ę

du na zako

ń

czenie poprzedniego 

scheduleAtFixedRate (TimerTask task, long delay, long okres)

  

scheduleAtFixedRate (TimerTask task, Date firstTime, long okres)

  

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 4 

 

Jednokrotne asynchroniczne wykonanie zadania 

po upływie czasu

 

Przykład.

  Zastosujemy  klasy 

Timer

 

TimerTask

 

dla  asynchronicznego 

wykonania zadania po upływie 5 sekund. 

import java.util.Timer; 
import java.util.TimerTask; 
public class Przypomnienie

 

{

  

// Klasa główna naszego zadania

 

   Timer timer;  
    public Przypomnienie(int sekundy) { 

// Konstruktor klasy głównej 

        timer = new Timer(); 

// (3) Tworzymy w

ą

tek - obiekt klasy 

Timer 

        timer.schedule(new PrzypomTimerTask(), sekundy*1000);  

// (4) 

// (4) Tworzymy obiekt naszego typu pochodnego od 

TimerTask

 i 

// wybieramy go do wykonania po upływie 5000 ms 

    } 

// W klasie głównej definiujemy klas

ę

 wewn

ę

trzn

ą

 -  

// (1) definiujemy własn

ą

 klas

ę

 pochodn

ą

 po 

TimerTask

    class PrzypomTimerTask extends TimerTask {  
        public void run() { 

// (2) Metoda 

run()

 wykonuje zadanie w

ą

tku

 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 5 

            System.out.println("Czas minął!"); 
            timer.cancel();  

// Zako

ń

cz w

ą

tek – obiekt 

timer 

        } 
    } 
    public static void main(String args[]) { 

// Metoda main() klasy głównej 

        System.out.println("Wybieranie zadania."); 
        new Przypomnienie(5); 

// Konstrukcja obiektu klasy głównej

 

        System.out.println("Zadanie wybrane."); 
    } 

 
Wynik: 
   

Zadanie wybrane. 

Czas minął  
 

Drugi napis pojawi si

ę

 po 5 sekundach po pierwszym.  

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 6 

Jednokrotne asynchroniczne wykonanie zadania 

o okre

ś

lonej porze

 

Przykład.

  Wykonanie  zadania  o  godzinie  23:01.  W  tre

ś

ci  konstruktora 

naszej klasy 

Przypomnienie

 : 

public Przypomnienie(int sekundy) { 

 

 

// Pobierz dzisiejsz

ą

 dat

ę

 

   Calendar calendar = Calendar.getInstance(); 

 

   calendar.set(Calendar.HOUR_OF_DAY, 23); 

// Ustaw godzin

ę

 

   calendar.set(Calendar.MINUTE, 1); 
   calendar.set(Calendar.SECOND, 0); 
   Date time = calendar.getTime();  
   timer = new Timer(); 

// Utwórz w

ą

tek nadzoruj

ą

cy czas

 

  

// Wykonaj w

ą

tek zadania o podanej godzinie tego dnia: 

   timer.schedulenew PrzypomTimerTask(), time); 

 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 7 

Zatrzymanie w

ą

tków klasy Timer jest mo

Ŝ

liwe na 4 sposoby: 

1.  wywołanie metody 

cancel()

 dla obiektu klasy 

Timer

 (jak powy

Ŝ

ej); 

2.  utworzy

ć

 w

ą

tek - „demon” wywołaniem konstruktora: 

new Timer(true) ;

 

program  którego  jedynymi  w

ą

tkami  pozostały  w

ą

tki  demony  zako

ń

czy 

si

ę

  (w  podanych  przykładach  nie  mo

Ŝ

na  tak  post

ą

pi

ć

,  gdy

Ŝ

  czekamy 

na wykonanie si

ę

 zadania zleconego przez obiekt klasy 

Timer

); 

3.  usun

ąć

  wszystkie 

referencje

  do  obiektu  klasy 

Timer

,  mo

Ŝ

e  to 

zako

ń

czy

ć

 w

ą

tek obiektu 

Timer

-a. 

4.  wywołanie metody 

System.exit

 zako

ń

czy cały program - w tym jego 

w

ą

tki. 

 

Przykład.

  Dodanie  do  klasy 

Przypomnienie

  dzwonka  i  wywołanie 

metody 

System.exit

 w celu zako

ń

czenia programu. 

public class PrzypomnienieDzwonkiem { 

    ... 

    public PrzypomnienieDzwonkiem (int sekundy) { 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 8 

    toolkit = Toolkit.getDefaultToolkit(); 

// W celu uzyskania dzwonka 

    timer = new Timer(); 
    timer.schedule(new PrzypomTimerTask(), sekundy*1000); 

    } 

    // Klasa dla zadania w

ą

tku 

    class PrzypomTimerTask extends TimerTask 
        public void run() { 

            System.out.println(Czas minął!"); 
            toolkit.beep();  
           //timer.cancel(); 

// Teraz niepotrzebne, gdyŜ wołamy System.exit

 

          System.exit(0);   

// Zatrzyma w

ą

tek główny programu (i inne) 

           } 
    }   ... 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 9 

 

Wielokrotne, cykliczne wykonywanie zadania 

Przykład.

 Wybieramy wykonanie zadania cyklicznie raz na sekund

ę

public class DenerwujacyDzwonek { 
    Toolkit toolkit; 
    Timer timer; 
    public DenerwujacyDzwonek () {  
        toolkit = Toolkit.getDefaultToolkit(); 
        timer = new Timer(); 
        timer.schedule(new PrzypomTimerTask(),  
   

 

0,  

// początkowe oczekiwanie  

                 1*1000);  

// cyklicznie co okres czasu 1 sekundy

 

    } 
    class PrzypomTimerTask extends TimerTask {   
        int liczbaDzwonkow = 3; 
        public void run() {  
          if (liczbaDzwonkow != 0) {  
             toolkit.beep(); 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 10 

             System.out.println("Dzwoni!"); 
             liczbaDzwonkow--; 
          } else {  
                toolkit.beep();  
                System.out.println("Czas minął!"); 
                

//

timer.cancel(); 

//Niepotrzebne - wołamy System.exit

 

                System.exit(0);  

// Zatrzyma w

ą

tek główny (i inne)

 

 

              } 
          } 
    } 
    ... 

Wynik wykonania

:  

Zadanie wybrane.   

Dzwoni!       
Dzwoni!      // 1 sekunda po 1-szym "Dzwoni"  
Dzwoni!      // 1 sekunda po 2-im "Dzwoni" 
Czas minął! // 1 sekunda po 3-im "Dzwoni" 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 11 

6.3 Klasa 

Thread

 

Bazowa klasa w

ą

tków to 

java.lang.Thread

 - wprowadza m.in. 

metody



 

start()

 – 

rozpoczyna wykonywanie tre

ś

ci w

ą

tku zdefiniowanej w

 run() 



 

stop(),  stop(Throwable  obj);

 

-  (metody  niezabezpieczone)  zamiast 

nich nale

Ŝ

y sprawdza

ć

 warunek w 

run()

 i zako

ń

czy

ć

 odpowiednio t

ę

 

metod

ę

;

 



 

sleep(long  millis),  sleep(long  millis,  int  nanos)

 

–  u

ś

pienie  w

ą

tku  na 

pewien czas; 



 

yield()

 – 

czasowo zatrzymuje w

ą

tek i ustawia go na ko

ń

cu kolejki;

 



 

getPriority(), setPriority(int) – 

pobierze i ustawi priorytet w

ą

tku. 

 

1) Metoda 

run()

 

Implementacja 

w

ą

tku 

opartego 

na 

klasie 

Thread

 

wymaga 

zdefiniowania  metody 

void

 

run()

  -  zawera  ona  zadanie  wykonywane 

przez  w

ą

tek.  Klasa 

Thread

  zawiera  definicj

ę

  metody 

run()

  o 

pustym 

kodzie. 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 12 

Klasy mog

ą

 

tworzy

ć

 metody 

run()

 na 

dwa sposoby

1.  przez dziedziczenie po klasie 

Thread

 i nadpisanie metody 

run()

2.  przez  implementacj

ę

  interfejsu 

Runnable

  -  wtedy  klasa  musi 

zawiera

ć

 implementacj

ę

 metody 

run()

 

 

Dziedziczenie  po  klasie 

Thread

 

i  nadpisanie 

run() 

-  klasa 

Thread

  ju

Ŝ

 

implementuje 

Runnable

 

Przykład

Klasa 

ProstyWatek 

(implementuje 

wątek) 

klasa 

DemoDwaWatki (wywołuje dwa wątki klasy ProstyWatek):

 

public class ProstyWatek extends Thread { 
    public ProstyWatek(String str) { 

// Konstruktor klasy 

        super(str);  

// To nada nazwę wątkowi

 

    } 
    public void run() { 

// Metoda run() zawiera zadanie wątku

 

        for (int i = 0; i < 10; i++) { 

// Wykonuje pętlę 10 razy

 

            System.out.println(i + " " + getName());  

// Wyprowadza indeks

 

   

 

 

 

 

 

 

 

 

// iteracji i nazwę wątku 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 13 

            try {  
   

 

sleep((long)(Math.random() * 1000)); 

// Uśpiony przez

  

   

 

 

 

// pewien czas – ale maksimum 1 sekundę. 

            } catch (InterruptedException e) {} 
        } 
        System.out.println("Wykonane! " + getName()); 

// Wyprowadza 

   

 

 

 

 

 

 

//  komunikat,  w tym nazwę wątku.  

    } 

// Klasa 

DemoDwaWatki :

 

public class DemoDwaWatki { 
    public static void main (String[] args) { 

   

// Utwórz i uruchom w

ą

tek 

     new ProstyWatek ("Bahama").start();      

   

// Utwórz i uruchom drugi w

ą

tek

 

     new ProstyWatek ("Bermudy").start();    } 

Wynik - na przemian wyprowadzane s

ą

 wyniki kolejnych w

ą

tków: 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 14 

0 Bahama 
0 Bermudy 
1 Bermudy 
1 Bahama 
2 Bahama 
2 Bermudy 
3 Bermudy 
... 
Wykonane! Bermudy 
9 Bahama 
Wykonane! Bahama 

 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 15 

2) Implementacja interfejsu 

Runnable

 przez klas

ę

 programisty 

Przykład

.  Aplet 

Zegar

  wy

ś

wietla

ć

  b

ę

dzie  aktualny  czas  i  od

ś

wie

Ŝ

a

ć

 

obraz  co  sekund

ę

  -  wykonuj

ą

c  odpowiedni  w

ą

tek.  Klasa 

Zegar

 

implementuje interfejs 

Runnable

 - w tym metod

ę

 

run()

.  

import java.awt.Graphics; 
import java.util.*; 
import java.text.DateFormat; 
import java.applet.Applet; 
public class Zegar extends Applet implements Runnable { 
    private Thread watekZegara = null

// Identyfikator dla obiektu wątku 

 

    public void start() {  

// Metoda początkowa apletu 

        if (watekZegara

== 

null) { 

// Obiekt klasy Zegar przekaŜe siebie samego do konstruktora Thread –  
// w ten sposób przekazana zostanie równieŜ implementacja metody 
// run() właściwa dla klasy Zegar do obiektu klasy Thread.  

           watekZegara = new Thread(this, "Zegar"); 

//przekazanie do wątku 

           watekZegara.start()

// Uruchom wątek

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 16 

        } 
    } 

   // Zadanie w

ą

tku w metodzie 

run() 

    public void run() {  

 

        Thread mojWatek = Thread.currentThread(); 
        while 
(watekZegara 

== 

mojWatek) { 

            repaint(); 

// Metoda apletu wołająca metodę paint() 

            try   
              Thread.sleep
(1000); 

// Samo-zawieszenie wykonywania wątku  

            } catch (InterruptedException e){ 
            

// Gdy JVM przerwie "nasz sen" zakończymy wykonywanie pętli. 

            
        } 
    } 

   // Nadpisanie metody 

paint()

 apletu

 

    public void paint(Graphics g) {       
        Calendar cal = Calendar.getInstance(); 

// Pobierz dzisiejszą datę

  

        Date date = cal.getTime(); 

// Pobierz czas, sformatuj go i wyświetl

 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 17 

        DateFormat dateFormatter = DateFormat.getTimeInstance(); 
        g.drawString(dateFormatter.format(date), 5, 10); 
    } 

   

// Nadpisanie metody 

stop()

 klasy 

Applet

, nie 

Thread

 

    public void stop() { 

 

       watekZegara = null; 

//Zmienia warunek sprawdzany w metodzie run() 

    } 

 

Uwagi 



 Dzi

ę

ki  mechanizmowi  w

ą

tków  aplet 

Zegar

  nie  blokuje  wykonywania 

si

ę

 przegl

ą

darki. 



 Je

ś

li klasa ju

Ŝ

 dziedziczy po innej klasie ni

Ŝ

 

Thread

 (jak np. 

Zegar

 po 

Applet

)  to  stosujemy  2-gie  rozwi

ą

zanie  -  implementacj

ę

  interfejsu 

Runnable

.  



 W  przeciwnym  razie  -  stosujemy  rozwi

ą

zanie  1-sze  –  dziedziczenie 

naszej klasy po 

Thread

.  

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 18 

3) "Cykl 

Ŝ

ycia" w

ą

tku 

 

Nowo utworzony 

Wykonywany 

Zablokowany 

Zako

ń

czony 

Zako

ń

czenie metody run() 

yield 

start 

 

Utworzenie w

ą

tku 

Np.  w  metodzie 

start() 

apletu  tworzony  jest  w

ą

tek  o  nazwie 

watekZegara

public void start() { 
    if (watekZegara == null) { 

        watekZegara = new Thread(this, "Zegar"); 

        watekZegara.start(); 

    } 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 19 

}     

Po  utworzeniu  w

ą

tek 

watekZegara

  jest  w  stanie  „

nowo  utworzony

” 

(„

new  Thread

”)

  -  jest  pustym  obiektem  klasy 

Thread

  bez  zasobów 

systemowych.  Mo

Ŝ

na  go  jedynie  uruchomi

ć

  -  metod

ą

 

start()

  (inne 

odwołanie spowoduje powstanie wyj

ą

tku 

IllegalThreadStateException

).  

 

Uruchomienie w

ą

tku  

public void start() {   
    if (watekZegara 

==

 null) { 

        watekZegara = new Thread(this, "Zegar");  

        watekZegara.start(); 

    } 
}   

Powstaj

ą

 zasoby systemowe dla w

ą

tku, wybierany jest w

ą

tek i wołana 

jest  dla  niego  metoda 

run()

.  W

ą

tek  b

ę

dzie  w  stanie  "

wykonywania

(

running

). 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 20 

Zablokowanie (zawieszenie) w

ą

tku 

Wykonywanie w

ą

tku zostaje 

zawieszone

 (stan „

zablokowany

”), gdy: 



 wywołana zostanie jego metoda 

sleep()

;

 



 w

ą

tek woła metod

ę

 

wait()

 dla oczekiwania na spełnienie warunku; 



 w

ą

tek zablokuje si

ę

 w oczekiwaniu na operacj

ę

 we/wy. 

Aby w

ą

tek powrócił do stanu „wykonywania” ze stanu „zablokowania”: 



 musi  upłyn

ąć

  okre

ś

lony  w  wywołaniu 

sleep()

  czas  podany  liczb

ą

 

milisekund; 



 inny obiekt musi powiadomi

ć

 nasz u

ś

piony w

ą

tek o zmianie warunku 

wywołuj

ą

notify

 lub 

notifyAll

 ; 



 operacja we/wy, blokuj

ą

ca w

ą

tek, musi si

ę

 zako

ń

czy

ć

Ust

ą

pienie czasu procesora innym w

ą

tkom 

W

ą

tek  mo

Ŝ

e  samoczynnie  ust

ą

pi

ć

  czas  procesora 

bez  przechodzenia

 

w  stan 

zawieszenia

  wołaj

ą

c  metod

ę

 

yield()

  –  przejdzie  on  na  koniec 

kolejki w

ą

tkom o jego priorytecie i da szans

ę

 na wykonanie si

ę

 innym 

w

ą

tkom o tym samym priorytecie co ust

ę

puj

ą

cy w

ą

tek. 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 21 

Zako

ń

czenie w

ą

tku 

W

ą

tek ko

ń

czy si

ę

 samodzielnie gdy zako

ń

czy si

ę

 metoda 

run(). 

W  przykładzie  z  apletem 

Zegar

  o  zako

ń

czeniu  p

ę

tli  metody 

run()

 

decyduje warunek: 

while (watekZegara 

== 

mojWatek) { 

Gdy przegl

ą

darka opuszcza stron

ę

, na której wykonuje si

ę

 aplet wtedy 

woła ona metod

ę

 

stop()

 dla apletu. W aplecie 

Zegar

 oznacza to, 

Ŝ

e: 

public void stop() {  
    watekZegara = null; 

// Zmieniamy warunek wykonywania się run() 

Teraz metoda 

run()

 zako

ń

czy si

ę

 -> w

ą

tek jest w stanie „

zako

ń

czony

”. 

Metoda klasy 

Thread: isAlive()

 

boolean

 

isAlive()

 

Wynik zwracany przez 

isAlive

:  



 

true

 - gdy w

ą

tek jest w stanie „wykonywania” lub „zablokowania”; 



 

false 

- gdy w

ą

tek jest w stanie 

nowo utworzony

” lub

 „zako

ń

czony”. 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 22 

4) Priorytet w

ą

tku - szeregowanie 

Priorytet  w

ą

tku  decyduje  o  przydzieleniu  czasu  procesora  jednemu  z 

w

ą

tków  b

ę

d

ą

cych  w  stanie  „wykonywania”  –  wybraniu  go  spo

ś

ród 

konkuruj

ą

cych w

ą

tków.  

 
Java 

realizuje 

deterministyczny 

algorytm 

szeregowania 

(„scheduling”) w oparciu o priorytety



 W

ą

tek dziedziczy swój priorytet od w

ą

tku który go utworzył. 



 Metoda 

setPriority

 umo

Ŝ

liwia zmian

ę

 priorytetu - mo

Ŝ

liwe s

ą

 warto

ś

ci 

od 

MIN_PRIORITY

  do 

MAX_PRIORITY

  (stałe  zdefiniowane  w 

Thread

).  



 Wybierany jest w

ą

tek o najwy

Ŝ

szym priorytecie - z dwóch równych 

nast

ę

pny z kolejki FIFO dla danego priorytetu.  

 

W

ą

tek  wykonuje  si

ę

  w  procesorze  dopóki  nie  zajdzie  jeden  z 

przypadków: 



 Pojawi si

ę

 w

ą

tek o wy

Ŝ

szym priorytecie - w stanie „

wykonywania

”  

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 23 



 W

ą

tek ust

ę

puje sam (metoda 

yield

)

 lub ko

ń

czy si

ę

 jego metoda 

run



 W  systemach  pracuj

ą

cych  z  podziałem  czasu  w

ą

tków  –  gdy  jego 

kwant czasu ko

ń

czy si

ę

 (zale

Ŝ

y to od implementacji klasy 

Thread

). 

 

Wtedy kolejny w

ą

tek b

ę

dzie wybrany do wykonania. 

 
Algorytm wyboru jest 

wywłaszczaj

ą

cy

 - z chwil

ą

 pojawienia si

ę

 w

ą

tku 

o wy

Ŝ

szym priorytecie wykonywany w

ą

tek zostaje wywłaszczony. 

 
Java 

nie  realizuje  podziału  czasu

,  w

ą

tek  nie  zostanie  wywłaszczony 

przez  inny  w

ą

tek  o  tym  samym  priorytecie.  Jednak  implementacja 

klasy 

Thread

  w  danym  systemie  mo

Ŝ

e  realizowa

ć

  prac

ą

  z  podziałem 

czasu CPU.  

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 24 

6.4 Synchronizacja pracy w

ą

tków 

Do  tej  pory  rozpatrywali

ś

my  w

ą

tki,  które  mog

ą

  wykonywa

ć

  si

ę

 

asynchronicznie 

wzgl

ę

dem 

siebie. 

Jednak 

w

ą

tki 

mog

ą

 

wykorzystywa

ć

  wyniki  pracy

  innych  w

ą

tków.  W  szczególno

ś

ci  w

ą

tki 

mog

ą

 

dzieli

ć

  te  same  dane  –  jednocze

ś

nie  odwoływa

ć

  si

ę

  do  nich

Wtedy ich praca musi by

ć

 synchronizowana

 

Przykład.  
Producent

 generuje dane, zapisuje je do obiektu sklad klasy Skladzik a 

te  s

ą

  nast

ę

pnie  odczytywane  i  "konsumowane"  przez 

konsumenta

Niech  producent  generuje  liczb

ę

  pomi

ę

dzy  0  a  9  (wł

ą

cznie), 

zapami

ę

tuje  j

ą

  w  obiekcie  klasy 

Skladzik

  i  wy

ś

wietla  t

ę

  liczb

ę

Nast

ę

pnie "zasypia" na losowo dobierany czas (pomi

ę

dzy 0 a 100 ms) 

i znowu powtarza cykl generacji danych. 

public class Producent extends Thread { 
    private Skladzik sklad; 
    private int number; 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 25 

    public Producent (Skladzik c, int number) { 
        sklad = c; 
        this.number = number; 
    } 
    public void run() { 
        for (int i = 0; i < 10; i++) { 
            skład.put(i); 
            System.out.println("Producent #" + this.number + " połoŜył: " + i); 
            try { 
                sleep((int)(Math.random() * 100)); 
            } catch (InterruptedException e) { } 
        } 
    } 

Konsument pobiera wszystkie liczby jak szybko to jest mo

Ŝ

liwe. 

public class Konsument extends Thread { 
    private Skladzik sklad; 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 26 

    private int number; 
    public Konsument(Skladzik c, int number) { 
        sklad = c; 
        this.number = number; 
    } 
    public void run() { 
        int value = 0; 
        for (int i = 0; i < 10; i++) { 
            value = sklad.get(); 
         System.out.println("Konsument #" + this.number+"pobrał: "+ value); 
        } 
    } 

// Klasa główna programu 

public class ProducentKonsumentTest { 
    public static void main(String[] args) { 
        Skladzik c = new Skladzik(); 
        Producent p1 = new Producent(c, 1); 

// Utwórz producenta 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 27 

        Konsument c1 = new Konsument(c, 1); 

// Utwórz konsumenta 

        p1.start(); 

// Uruchom wątek producenta 

        c1.start(); 

// Uruchom wątek konsumenta

 

    } 

 

Producent  i  konsument  wymieniaj

ą

  dane  poprzez 

wspólny  obiekt

 

Skladzik

.  Ale  obie  klasy  "

Konsument

"  i  "

Producent

nie  synchronizuj

ą

 

jawnie  swoich  działa

ń

,  nie  zapewniaj

ą

  tego, 

Ŝ

eby  konsument 

otrzymywał ka

Ŝ

d

ą

 dan

ą

 

tylko raz

.  

Dlatego  w  tym  przykładzie  synchronizacja 

musi  by

ć

  zrealizowana  na 

"niskim  poziomie"

  przez  metody  "

get

"  i  "

put

"  klasy 

Składzik

.  W  innym 

przypadku  łatwo  mo

Ŝ

e  powsta

ć

  "

hazard

"  w  dost

ę

pie  do  obiektu  przez 

oba w

ą

tki. 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 28 

Sposoby synchronizacji: 



 

zablokowanie  innemu  w

ą

tkowi  dost

ę

pu  do  obiektu 

(sekcja 

krytyczna

– kwalifikator metody

  

synchronized 

.

 



 

powiadamianie  si

ę

  w

ą

tków  -  metody  klasy 

Thread 

wait,  notify

notifyAll

Sekcja krytyczna 

Przykład (c.d.)

 W podanym przykładzie metody 

put

 i 

get 

klasy 

Skladzik

 

tworz

ą

 sekcje krytyczne. 

public class Skladzik { 
    private int contents; 
    private boolean available = false; 
    public synchronized int get() { 
        ... 
    } 
    public synchronized void put(int value) { 
        ... 
    } 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 29 

Z  ka

Ŝ

dym  obiektem  klasy 

Skladzik

  zwi

ą

zany  b

ę

dzie 

semafor

.  Je

ś

li 

wołana  jest  metoda  synchronizowana  to  obiekt  zostaje  zablokowany. 

Inny  w

ą

tek  nie  mo

Ŝ

e  wykona

ć

  metody  synchronizowanej

  na  tym 

samym  obiekcie  do  momentu  odblokowania  obiektu.  Uniemo

Ŝ

liwia  to 

powstanie hazardu w dost

ę

pie do obiektu. 

 

Metody 

notifyAll

  i  

wait

 

 

W

ą

tki musz

ą

 si

ę

 móc powiadamia

ć

Ŝ

e czekaj

ą

 na nie dane (

wait

) i 

Ŝ

dane zostały dostarczone (

notify, notifyAll

). 

Przykład (c.d.)

 Nowe definicje metod 

get

 i 

put

 klasy 

Skladzik

 

public synchronized int get() { 
    while (available == false) { 
        try { 
                wait(); 

// Oczekuj na połoŜenie danej przez producenta

 

        } catch (InterruptedException e) { 
        } 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 30 

    } 
    available = false; 
    notifyAll(); 

// Powiadom producenta o pobraniu danej

  

    return contents; 

public synchronized void put(int value) { 
    while (available == true) { 
        try { 
                wait(); 

// Oczekuj na pobranie danej przez konsumenta

 

        } catch (InterruptedException e) { 
        } 
    } 
    contents = value; 
    available = true;

 

    notifyAll(); 

// Powiadom konsumenta o połoŜeniu danej 

Metod 

wait

  zwalnia  semafor  "trzymany"  przez  "Konsumenta"  na 

obiekcie "sklad" i oczekuje na powiadomienie od "Producenta".  

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 31 



 Metoda 

notifyAll

 

budzi  do 

Ŝ

ycia  wszystkie  w

ą

tki,  które  oczekuj

ą

  na 

dany  obiekt  (w  tym  przypadku  "sklad").  Konkuruj

ą

  one  wtedy  o 

dost

ę

p do obiektu. 

 



 Metoda 

notify

  w  klasie 

Object

:  "budzi"  dowolny  w

ą

tek  spo

ś

ród 

oczekuj

ą

cych. 

 



 W klasie 

Object

 zdefiniowano trzy wersje metody 

wait



 

wait()

 - oczekuje w niesko

ń

czono

ść

 na nadej

ś

cie powiadomienia; 



 

wait (long timeout)

  - oczekuje najwy

Ŝ

ej liczb

ę

 

timeout 

milisekund; 



 

wait  (long  timeout,  int  nanos)

  -  oczekuje  najwy

Ŝ

ej  liczb

ę

 

timeout 

milisekund plus 

nanos

 nanosekund. 

 

Nale

Ŝ

y unika

ć

 "wygłodzenia” i zakleszcze

ń

 w

ą

tków. 

"Wygłodzenie"  w

ą

tku  wyst

ą

pi  gdy  jeden  lub  wi

ę

cej  w

ą

tków  nie 

otrzymuje dost

ę

pu do zasobów. 

Zakleszczenie  to  ko

ń

cowe  stadium  „wygłodzenia”  -  w

ą

tki  czekaj

ą

  na 

spełnienie niemo

Ŝ

liwego warunku. 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 32 

6.5 Grupowanie w

ą

tków  

Klasa 

java.lang.ThreadGroup  -

 

umo

Ŝ

liwia  zebranie  w

ą

tków  w  jeden 

obiekt i jednoczesn

ą

 manipulacj

ę

 nimi wszystkimi.  

Podczas  tworzenia  w

ą

tku  zostaje  on  przydzielony  do  jakie

ś

  grupy  i 

musi ju

Ŝ

 tam pozosta

ć

Domy

ś

lna grupa w

ą

tków dla aplikacji to jest 

main

 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 33 

Utworzenie nowej grupy w

ą

tków o nazwie 

name

:  

 

ThreadGroup(String name)  

 

ThreadGroup(ThreadGroup parent, String name)  

Np. utworzenie grupy jako elementu domy

ś

lnej grupy w

ą

tków 

main

ThreadGroup myThreadGroup = new ThreadGroup(“Moja grupa");

 

Je

ś

li podczas tworzenia nowego w

ą

tku nie specyfikujemy jego grupy to 

zostanie on zaliczony do grupy tego w

ą

tku, który go utworzył. 

 
Trzy konstruktory klasy 

Thread

 umo

Ŝ

liwiaj

ą

 utworzenie i dodanie w

ą

tku 

do jawnie podanej grupy: 

public Thread(ThreadGroup group, Runnable runnable
public Thread(ThreadGroup group, String name
public Thread(ThreadGroup group, Runnable runnable, String name

Np. 

Utworzenie w

ą

tku w nowej grupie:  

Thread myThread = new Thread(myThreadGroup, "watek w grupie"); 

 
Okre

ś

lenie grupy dla w

ą

tku - metoda 

getThreadGroup

, np.: 

theGroup = myThread.getThreadGroup(); 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 34 

Metody klasy

 

ThreadGroup

 

Zarz

ą

dzanie kolekcj

ą

  



 

activeCount() 

- podaje liczb

ę

 aktywnych w

ą

tków w grupie;  



 

activeGroupCount()

 – podaje liczb

ę

 aktywnych grup w

ą

tków w grupie

.

 

Klasa implementuje interfejs 

Enumerate

, co pozwala m.in. na pobranie 

listy aktywnych w

ą

tków tej grupy.  

Np. 

public class EnumerateTest { 
    public void listCurrentThreads() { 
        ThreadGroup currentGroup = 
                    Thread.currentThread().getThreadGroup(); 
        int numThreads = currentGroup.activeCount(); 
        Thread[] listOfThreads = new Thread[numThreads]; 
        currentGroup.enumerate(listOfThreads); 
        for (int i = 0; i < numThreads; i++) 
System.out.println("Wątek #" + i + " = " + listOfThreads[i].getName()); 
    } 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 35 

Przetwarzanie grupy w

ą

tków 



 

getMaxPriority, setMaxPriority  

// Ustawianie priorytetu

 



 

getDaemon, setDaemon  



 

getName  



 

getParent, parentOf  



 

toString  

Np. 

public class MaxPriorityTest { 
   public static void main(String[] args) { 
      ThreadGroup groupNORM = new ThreadGroup

// Utworzenie grupy 

                                    "Normalny priorytet grupy");  
      Thread priorityMAX = new Thread(groupNORM, 

// Dodanie wątku

 

                                 "Wątek o maksymalnym priorytecie"); 

      // Ustaw priorytet wątku na maksymalnie moŜliwy (10)  

        priorityMAX.setPriority(Thread.MAX_PRIORITY); 

      // Ustaw maksymalny priorytet grupy na normalny (5) 

      groupNORM.setMaxPriority(Thread.NORM_PRIORITY); 

        System.out.println("Maksymalny priorytet grupy = " + 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 36 

   

 

   groupNORM.getMaxPriority()); 

        System.out.println("Priorytet wątku = " + priorityMAX.getPriority()); 
    } 

Wynik wykonania: 

Maksymalny priorytet grupy  = 5 
Priorytet wątku = 10 

 

Metody operuj

ą

ce na stanie wszystkich w

ą

tkach grupy jednocze

ś

nie 



 

resume() - 

wznów 



 

stop() 

zatrzymaj 



 

suspend()  

zawie

ś

 

Metody te zmieniaj

ą

 stan wszystkich w

ą

tków grupy jednocze

ś

nie. 

 

Uwaga:  poniewa

Ŝ

  wykorzystuj

ą

  one  metody 

resume,  stop

  i 

suspend

 

klasy 

Thread

  nie  s

ą

  one  zabezpieczone  przed  w

ą

tkami  (tzn. 

jednoczesnym u

Ŝ

yciem przez wi

ę

cej ni

Ŝ

 jeden w

ą

tek). 

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 37 

Metody kontroli dost

ę

pu 

Obie klasy współpracuj

ą

 z klas

ą

 

SecurityManager

 . 

Klasy 

Thread

  i 

ThreadGroup

  posiadaj

ą

  metod

ę

 

checkAccess

,  która 

wywołuje  metod

ę

 

checkAccess

  aktualnego  „security  managera”, 

sprawdzaj

ą

c

ą

  prawo  dost

ę

pu  dla  grupy  -  zgłasza  wyj

ą

tek 

SecurityException

 

je

ś

li nie jest to mo

Ŝ

liwe. 

Poni

Ŝ

sze  metody  klasy 

ThreadGroup

  wywołuj

ą

  metod

ę

 

checkAccess

 

zanim wykonaj

ą

 swoj

ą

 akcj

ę

 (regulowany dost

ę

p): 

 

ThreadGroup(ThreadGroup parent, String name)  

 

setDaemon(boolean isDaemon)  

 

setMaxPriority(int maxPriority)  

 

stop  

 

suspend  

 

resume  

 

destroy  

 

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 38 

Lista metod klasy 

Thread

, które wywołuj

ą

 

checkAccess

 zanim wykonaj

ą

 

swoj

ą

 akcj

ę

 

konstruktory specyfikujące grupę wątków;  

 

stop  

 

suspend  

 

resume  

 

setPriority(int priority)  

 

setName(String name)  

 

setDaemon(boolean isDaemon)  

background image

6. W

ą

tki. 

W. Kasprzak: Programowanie zdarzeniowe 

6 - 39 

Podsumowanie 

Pakiety wspomagaj

ą

ce programowanie wielow

ą

tkowe 



 

java.lang.Thread - 

Bazowa klasa dla w

ą

tków w Javie.  



 

java.lang.Runnable 

Interfejs 

Runnable

  zawiera  metod

ę

 

run

wymagan

ą

 dla ka

Ŝ

dego w

ą

tku. 



 

java.lang.Object  - 

Klasa  główna 

Object

  zawiera  definicje  3  metod 

przeznaczonych do synchronizacji w

ą

tków

wait, notify, notifyAll

.  



 

java.lang.ThreadGroup  - 

Ka

Ŝ

dy  w

ą

tek  nale

Ŝ

y  do  jakie

ś

  grupy, 

zwykle skupiaj

ą

cej powi

ą

zane ze sob

ą

 w

ą

tki.  



 

java.lang.ThreadDeath 

Wymuszenie zako

ń

czenia pracy w

ą

tku jest 

mo

Ŝ

liwe dzi

ę

ki 

przekazaniu

 mu obiektu klasy 

ThreadDeath

 

Elementy j

ę

zyka wspomagaj

ą

ce w

ą

tki 

Słowo  kluczowe  w  Javie  przeznaczone  do  synchronizacji  w

ą

tków: 

synchronized

 

Elementy 

ś

rodowiska wykonania wspomagaj

ą

ce w

ą

tki 

ś

rodowisku wykonania Javy wyst

ę

puje szeregowanie w

ą

tków.