Programowanie wielowątkowe: podstawowe koncepcje, narzędzia w Javie. J. Starzyński, JiMP2, rok akad. 2005/2006

Podobne dokumenty
Wątki. Definiowanie wątków jako klas potomnych Thread. Nadpisanie metody run().

Obliczenia równoległe i rozproszone w JAVIE. Michał Kozłowski 30 listopada 2003

Język Java wątki (streszczenie)

Współbieżność w środowisku Java

Java. Wykład. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ

Kurs programowania. Wykład 8. Wojciech Macyna. 10 maj 2017

Kurs programowania. Wykład 8. Wojciech Macyna

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1

Język Java wątki (streszczenie)

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Wielowątkowość. Programowanie w środowisku rozproszonym. Wykład 1.

Programowanie komputerów

1 Wątki 1. 2 Tworzenie wątków 1. 3 Synchronizacja 3. 4 Dodatki 3. 5 Algorytmy sortowania 4

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego

Współbieżność w Javie

Wątki w Javie. Piotr Tokarski

Współbieżność w Javie

Aplikacje w Javie- wykład 11 Wątki-podstawy

Podstawy współbieżności

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

Interfejsy w Java. Przetwarzanie równoległe. Wątki.

WSPÓŁBIEŻNOŚĆ. MATERIAŁY:

Programowanie wielowątkowe. Tomasz Borzyszkowski

Języki i Techniki Programowania II. Wykład 7. Współbieżność 1

Java. Programowanie Obiektowe Mateusz Cicheński

Programowanie równoległe i rozproszone. W1. Wielowątkowość. Krzysztof Banaś Programowanie równoległe i rozproszone 1

Przetwarzanie równoległe i współbieżne

Wątki (Threads) Potrzeby. Przetwarzanie równoległe i współbieŝne. Cechy programowania wątkowego. Concurrent programming is like

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Programowanie współbieżne i rozproszone

Programowanie współbieżne Wykład 2. Rafał Skinderowicz

Programowanie równoległe i rozproszone. Monitory i zmienne warunku. Krzysztof Banaś Programowanie równoległe i rozproszone 1

Programowanie obiektowe

Wielowątkowość mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Programowanie współbieżne Laboratorium nr 12

Wykład 8: Obsługa Wyjątków

4.1 Napisz kod, w którym definiujesz, tworzysz oraz uruchamiasz wątki z uŝyciem klas java.lang.thread oraz java.lang.runnable.

Język JAVA podstawy. Wykład 3, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

W Javie wątki są obiektami zdefiniowanymi za pomocą specjalnego rodzaju klas.

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Programowanie współbieżne Wykład 5. Rafał Skinderowicz

1. Co można powiedzieć o poniższym kodzie (zakładając, że zaimportowano wszystkie niezbędne klasy)?

Systemy Rozproszone - Ćwiczenie 4

Wielowątkowość 1. Marcin Orchel. AGH University of Science and Technology in Poland 1 / 58

1. Co można powiedzieć o poniższym kodzie? public interface I { void m1() {}; static public void m2() {}; void abstract m3();

Multimedia JAVA. Historia

Wykład 4: Klasy i Metody

Stworzenie klasy nie jest równoznaczne z wykorzystaniem wielowątkowości. Uzyskuje się ją dopiero poprzez inicjalizację wątku.

Zaawansowane programowanie w C++ (PCP)

Operatory. Składnia. Typy proste. Znaki specjalne

1. Co można powiedzieć o poniższym kodzie (zakładając, że znajduje się on w jednym pliku A.java)?

Programowanie współbieżne Laboratorium nr 11

Programowanie w Javie 1 Wykład i Ćwiczenia 3 Programowanie obiektowe w Javie cd. Płock, 16 października 2013 r.

Programowanie w Sieci Internet. Python: Wątki. Kraków, 12 grudnia 2014 r. mgr Piotr Rytko Wydział Matematyki i Informatyki

Semafor nie jest mechanizmem strukturalnym. Aplikacje pisane z użyciem semaforów są podatne na błędy. Np. brak operacji sem_post blokuje aplikację.

Semafor nie jest mechanizmem strukturalnym. Aplikacje pisane z użyciem semaforów są podatne na błędy. Np. brak operacji sem_post blokuje aplikację.

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Programowanie i projektowanie obiektowe

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

Systemy Rozproszone - Ćwiczenie 6

1. Co można powiedzieć o poniższym kodzie?

1 Atrybuty i metody klasowe

Przykłady interfejsu TCP i UDP w Javie

Aplikacja wielowątkowa prosty komunikator

Model pamięci. Rafał Skinderowicz

Polimorfizm, metody wirtualne i klasy abstrakcyjne

7 Pewne uzupełnienia Przepływ sterowania Układacze... 6

Programowanie obiektowe

Systemy operacyjne. Zajęcia 11. Monitory

Technologie i usługi internetowe cz. 2

Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków

Aplikacje Internetowe. Najprostsza aplikacja. Komponenty Javy. Podstawy języka Java

Kurs programowania. Wykład 9. Wojciech Macyna

Metody Metody, parametry, zwracanie wartości

Obiektowe programowanie rozproszone Java RMI. Krzysztof Banaś Systemy rozproszone 1

Java EE produkcja oprogramowania

Generatory. Michał R. Przybyłek

1. Co będzie wynikiem wykonania poniŝszych instrukcji? g2d.gettransform().scale(1, -1); g2d.gettransform().translate(4, -8); g2d.drawline(4, 0, 4, 4);

Programowanie obiektowe

Programowanie obiektowe

Dokumentacja do API Javy.

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Podejście obiektowe. Tablice obiektów Przykład 1 metody i atrybuty statyczne oraz niestatyczne

Podstawy programowania obiektowego

Polimorfizm. dr Jarosław Skaruz

Laboratorium 03: Podstawowe konstrukcje w języku Java [2h]

WIELOWĄTKOWOŚĆ. Waldemar Korłub. Platformy Technologiczne KASK ETI Politechnika Gdańska

Wykład 2: Podstawy Języka

Podstawy i języki programowania

Zofia Kruczkiewicz, Programowanie obiektowe - java, wykład 2 1

Programowanie obiektowe

KLASY, INTERFEJSY, ITP

Java SE, Laboratorium nr 8 Wątki

Tworzenie i wykorzystanie usług

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Równolegªo± w Javie w tki.

Aplikacje RMI Lab4

Java: interfejsy i klasy wewnętrzne

Transkrypt:

Programowanie wielowątkowe: podstawowe koncepcje, narzędzia w Javie J. Starzyński, JiMP2, rok akad. 2005/2006

Tematyka Wprowadzenie Podstawowe pojęcia Tworzenie i uruchamianie wątków Zatrzymywanie wątków Współdzielenie pamięci synchronizacja Komunikacja pomiędzy wątkami Hierarchie i priorytety wątków

Wprowadzenie Większość programów działa w środowiskach sekwencyjnych, gdzie procesor wykonuje ciąg instrukcji jedna po drugiej. Wiele programów wymaga jednak równoległego wykonywania więcej niż jednego ciągu operacji. Taką równoległość symuluje się przez cykliczne przełączanie procesora.

Wprowadzenie, c.d. Proces to samodzielnie wykonujący się program z własną przestrzenią adresową. Wielozadaniowy system operacyjny jest w stanie uruchomić jednocześnie wiele procesów. Każdy z nich może działać niezależnie od innych, a system przydziela każdemu pewien przedział czasu procesora. Wątek to niezależne podzadanie w ramach procesu. Może współdzielić pamięć z innymi wątkami.

Wprowadzenie, c.d. W Javie można tworzyć wątki jako rozdzielne sekwencje strowania. Do czego się to przydaje? sterowanie obsługa urządzeń programowanie grafiki interakcyjnej programowanie równoległe i rozproszone while( 1 ) { t1= gettemperature( sensor1 ); t2= gettemperature( sensor2 ); t3= gettemperature( sensor3 ); p1= getpressure( sensor5 ); p2= getpressure( sensor6 ); if( t1 > TMAX t2 > TMAX ) stopheater( h1 ); if( t1 < t2 ) switchheater( h2 ); if( t3 > TMAX && p1 > PMAX ) openvalve( );

Wprowadzenie, c.d. Model odsłuchowy while( n_nodes > 4 ) { check_sharp_edges( &n_nodes, nodes, x, y, np, nop, ne ); if( n_nodes < 5 ) break; if( userinput() ) /* sprawdzamy, czy uzytkownik sie nie znudzil */ break; find_edge_seq( &n_nodes, nodes, x, y, np, nop, ne, &l_seq, &ptr ); if( userinput() ) /* sprawdzamy, czy uzytkownik sie nie znudzil */ break; if( l_seq > 1 ) close_edge_seq( &n_nodes, nodes, x, y, np, nop, ne, &l_seq, &ptr ); else catalizer( &n_nodes, nodes, x, y, np, nop, ne ); if( n_nodes < 5 ) break; if( userinput() ) /* sprawdzamy, czy uzytkownik sie nie znudzil */ break; if( userinput() ) /* uzytkownik sie znudzil */ processuserinput();

Wprowadzenie, c.d. Model zdarzeniowy int kbd_listener( int key_pressed ) { if( key_pressed == CTRL_C ) ask_if_really_stop(.); register_listener( kbd_listener ); while( n_nodes > 4 ) { check_sharp_edges( &n_nodes, nodes, x, y, np, nop, ne ); if( n_nodes < 5 ) break; find_edge_seq( &n_nodes, nodes, x, y, np, nop, ne, &l_seq, &ptr ); if( l_seq > 1 ) close_edge_seq( &n_nodes, nodes, x, y, np, nop, ne, &l_seq, &ptr ); else catalizer( &n_nodes, nodes, x, y, np, nop, ne );

Tworzenie wątków metoda A Klasę-wątek możemy utworzyć rozszerzając szkieletową klasę Thread Jeżeli wątek ma coś robić, to musimy w naszej klasie utworzyć metodę public void run() Ta metoda jest uruchamiana przez wywołanie metody start. Wątek,,żyje tak długo, jak długo działa jego metoda run

Tworzenie wątków przykład A class W1 extends Thread { String name; long delay; long nrepet; W1( String w, long dt, long n ) { name= w; delay= dt; nrepet= n; public void run() { try { for( int i= 0; i < nrepet; i++) { System.out.print( name + " " ); sleep( delay ); catch( InterruptedException 3 e ) { System.out.println( "Exiting " + name + "\n" ); return;

Tworzenie wątków przykład A, c.d. class W1Test { public static void main( String args[] ) throws InterruptedException { for( int i= 0; i < args.length; i += 3 ) new W1( args[i], Long.valueOf( args[i+1] ).longvalue(), Long.valueOf( args[i+2] ).longvalue() ).start();

Tworzenie wątków metoda B Klasę-wątek możemy utworzyć implementując interfejs Runnable Pozwala to utworzyć klasę-wątek, która rozszerza jakąś klasę, która nie jest wątkiem Podobnie, jak w metodzie A musimy w naszej klasie utworzyć metodę public void run() Klasę implementującą Runnable uruchamiamy w nieco bardziej skomplikowany sposób

Tworzenie wątków przykład B class W2 implements Runnable { String name; long delay; long nrepet; W2( String w, long dt, long n ) { name= w; delay= dt; nrepet= n; public void run() { try { for( int i= 0; i < nrepet; i++) { System.out.print( name + " " ); Thread.sleep( delay ); catch( InterruptedException e ) { System.out.println( "Exiting " + name + "\n" );

Tworzenie wątków przykład B, c.d. class W2Test { public static void main( String args[] ) throws InterruptedException { for( int i= 0; i < args.length; i += 3 ) { Runnable r= new W2( args[i], Long.valueOf( args[i+1] ).longvalue(), Long.valueOf( args[i+2] ).longvalue() ); new Thread( r ).start();

Zatrzymywanie wątków Program działa, dopóki działa choć jeden z jego wątków (z wyj. wątków-demonów). Każdy program ma przynajmniej jeden wątek jest nim metoda main uruchamianej klasy Wątek można zatrzymać komunikując się z jego metodą run tak jest najlepiej Można też zatrzymać wątek wysyłając mu przerwanie (wyjątek InterruptException) W starej Javie można też było wywołać metodę stop (zgłasza wyjątek ThreadDeath), ale jest to sposób przestarzały (niebezpieczny)

Zatrzymywanie wątków class Wx extends Thread { public boolean canrun; public void start() { canrun= true; super.start(); public void run() { while( canrun ) { // sprzątanie class WxUser { Wx t= new Wx(); t.start(); if( t_should_stop ) t.canrun = false;

Możliwe stany wątku Utworzony, ale nie uruchomiony Uruchomiony Zakończony (koniec run(), stop(), destroy()) Zablokowany sleep() suspend(). resume() yield() wait() we/wy czeka na zwolnienie monitora

Problem: dzielony dostęp do danych Wątek Kasa: stankonta = stankonta + wpłata; Wątek Bankomat: stankonta = stankonta - wypłata; stankonta rejestr stankonta rejestr rejestr += wpłata rejestr -= wpłata rejestr stankonta rejestr stankonta Stan konta nie uwzględnia wpłaty!

Synchronizacja Każdy obiekt zawiera monitor blokadę, która jest automatycznie jego częścią. Można wykorzystać ją (po to jest) do blokowania obiektu. Pierwszym sposobem jest deklarowanie metod, które powinny blokować obiekt jako synchronized Drugim sposobem jest użycie bloków synchronizowanych

Synchronizacja, c.d. class SP { private double x,y; SP( ) { x= 0; y= 0; public synchronized double x() { return x; public synchronized double y() { return y; public synchronized void move( double dx, double dy ) { x += dx; y += dy; public synchronized void newx( double x ) { this.x = x; public synchronized void newy( double y ) { this.y = y; public synchronized void movetoward( SP other, double a ) { this.x += ( other.x() - this.x ) * a; this.y += ( other.y() - this.y ) * a;

Synchronizacja, c.d. class SP { private double x,y; SP( ) { x= 0; y= 0; public synchronized double x() { return x; public synchronized double y() { return y; public synchronized void move( double dx, double dy ) { x += dx; y += dy; public synchronized void newx( double x ) { this.x = x; public synchronized void newy( double y ) { this.y = y; public synchronized void movetoward( SP other, double a ) { this.x += ( other.x() - this.x ) * a; this.y += ( other.y() - this.y ) * a;

Synchronizacja, c.d. Trzeba pamiętać o synchronizowaniu wszystkich metod, które mają dostęp do wrażliwych pól. Metoda niesynchronizowana nie sprawdza blokady. Każda klasa ma jeden monitor statyczny, który jest używany do synchronizowania metod statycznych. Synchronizowanie spowalnia program: czas wywołania metod synchronizowanych jest kilkakrotnie (B.Eckel 4 razy) dłuższy, niż metod niesynchronizowanych.

Blok synchronizowany synchronized ( syncobject ) { // kod synchronizowany public synchronized void run () { while( true ) { counter++; l1.settext( Integer.toString( counter ); try { sleep( delay ); catch( InterruptedException e ) { System.err.println( name + interrupted ); Synchronizacja, c.d. public void run () { while( true ) { synchronized( this ) { counter++; l1.settext( Integer.toString( counter ); try { sleep( delay ); catch( InterruptedException e ) { System.err.println( Interrupted ); /* Move polygon by [ dx, dy ] */ public static void move( Point[] polygon, double dx, double dy ) { synchronized( polygon ) { for( int i= 0; i < polygon.length; i++ ) polygon[i].move( dx, dy );

Synchronizacja -- zakleszczenie Wątek A p1.movetoward( p2, 0.25 ) blokada p1 Wątek B p2.movetoward( p1, 0.2 ) blokada p2 oczekiwanie na p2.. oczekiwanie na p1. Zakleszczenie może mieć postać bardziej złożoną zamkniętego łańcucha wątków czekających jeden na drugi. Java nie zawiera narzędzi, które pomagałyby unikać zakleszczenia trzeba odpowiednio projektować program. Metody stop(), suspend(), resume() są niezalecane właśnie ze względu na ryzyko zakleszczenia przy ich stosowaniu.

Obiekty volatile class Test { static int i = 0, j = 0; static void one() { i++; j++; static void two() { System.out.println("i=" + i + " j=" + j); class Test { static int i = 0, j = 0; static synchronized void one() { i++; j++; static synchronized void two() { System.out.println("i=" + i + " j=" + j); class Test { static volatile int i = 0, j = 0; static void one() { i++; j++; static void two() { System.out.println( "i=" + i + " j=" + j); percentdone= 0; while( true ) { g.drawstring( Double( percentdone ).tostring() + "%", 50,25 ); Thread.sleep( 500 );

Komunikacja między wątkami Wykorzystujemy do niej monitor obiektu i metody wait(), notify(), notifyall() Metody wait(), notify(), notifyall() powinny być wywoływane z kodu synchronizowanego, dla swojej własnej blokady(). wait() zwalnia blokadę obiektu i czeka na wywołanie notify() lub notifyall() związane z tą blokadą Są wersje wait() odmierzające czas i czekające bezwarunkowo. notify() budzi jeden z wątków (niewiadomo który) czekających na monitor danego obiektu. Metody zgłaszają IllegalMonitorStateException, jeśli wątek wywołujący nie jest właścicielem blokady (monitora).

Synchronizacja w czasie public class IndividualFitness extends Thread { // tu definicja klasy public class GA { // public void generation() { oldpopulation= newpopulation; IndividualFitness [] FitPool= new IndividualFitness[ populationsize ]; for( int i= 0; i < populationsize; i++ ) { newpopulation[i]= new Individual( oldpopulation ); FitPool[i]= new individualfitness( newpopulation[i] ); FitPool[i].start(); for( int i= 0; i < populationsize; i++ ) { FitPool[i].join(); newpopulation[i].setfitness( FitPool.result() ); populationstatistics( newpopulation ); //.. //..

Synchronizacja w czasie import java.util.stack; public class SQueue { private Stack q; public SQueue() { q = new Stack(); public synchronized void insert( Object o ) { q.push( o ); notify(); // powiadom watek pobierajacy public synchronized Object get() throws InterruptedException // z wait() { while( q.empty() ) wait(); // czekaj az element sie pojawi return q.pop();

Synchronizacja w czasie class SQFeeder extends Thread { int start; int delay; int nrepet; SQueue sq; SQFeeder( int s, int n, int dt, SQueue q ) { start= s; delay= dt; nrepet= n; sq= q;. public void run() { try { for( int i= start; i < start+nrepet; i++) { sq.insert( new Integer( i ) ); sleep( delay ); catch( InterruptedException e ) { System.out.println( "SQFeeder interrupted\n" ); return;

Synchronizacja w czasie class SQEater extends Thread { SQueue sq; SQEater( SQueue q ) { sq= q; public void run() { try { while( true ) System.out.println( sq.get() ); catch( InterruptedException e ) { System.out.println( "SQEater interrupted\n" ); return;

Synchronizacja w czasie public class SQTester { public static void main( String [] args ) throws InterruptedException // ze sleep() { SQueue q= new SQueue(); SQFeeder f= new SQFeeder( 0, 20, 250, q ); SQEater e= new SQEater( q ); f.start(); // start feeder Thread.sleep( 4000 ); // wait 4 s. e.start(); // start eater - it should print 15-0 immediately, // then 16-19 with 250 ms. pauses f.join(); // wait for feeder to finish e.interrupt(); // finish eater e.join(); // let him stop

Priorytety wątków Każdy wątek ma przyporządkowany określony priorytet - liczbę całkowitą z zakresu od Thread.MIN_PRIORITY do Thread.MAX_PRIORITY i standardową wartością Thread.NORM_PRIORITY. Początkowo wątek dziedziczy priorytet od swojego rodzica. Wartość priorytetu można odczytać przy pomocy metody getpriority i zmienić w dowolnej chwili przy pomocy setpriority. Priorytety służą do szeregowania wątków.

public static void setthreadspriority( ) { Priorytety wątków Thread tenwatek= Thread.currentThread(); // pobierz biezacy watek ThreadGroup tagrupa= tenwatek.getthreadgroup(); // i jego grupe Thread[] watki = new Thread[ tagrupa.activecount() + 50 ]; // activecount tylko estymuje (cos moglo umrzec i cos sie urodzic) tagrupa.enumerate( watki ); // pakujemy watki do tablicy tenwatek.setpriority( Thread.MAX_PRIORITY ); // mogl nie dostac MAX_PRIORITY, bo ograniczenia dla grupy to uniemozliwialy int otherpriority= tenwatek.getpriority() - 1; // ustawiamy innym mniejszy for( int i= 0; i < watki.length; i++ ) if( watki[i]!= null && watki[i]!= tenwatek ) watki[i].setpriority( otherpriority ); // ale potem cos innego mogloby zwiekszyc priorytet ktoregos z tych watkow //skuteczniej: tagrupa.setmaxpriority( otherpriority );

Grupy wątków Wątki podzielone są na grupy, które tworzą hierarchie (to znaczy, że wątek dziedziczy grupę od rodzica, ale może tworzyć nowe podgrupy w ramach swojej grupy). Do tworzenia hierarchii wątków służy klasa ThreadGroup. Obok regulacji bezpieczeństwa klasa ta umożliwia grupowe sterowanie wątkami i ich priorytetami.

Grupy wątków public static void stopthreads( ) { Thread tenwatek= Tread.currentThread(); // pobierz biezacy watek ThreadGroup tagrupa= tenwatek.getthreadgroup(); // i jego grupe Thread[] watki = new Thread[ tagrupa.activecount() + 50 ]; // activecount tylko estymuje (cos moglo umrzec i cos sie urodzic) tagrupa.enumerate( watki ) // przerywamy wszystkie z wyjatkiem biezacego for( int i= 0; i < watki.length; i++ ) if( watki[i]!= null && watki[i]!= tenwatek ) watki[i].interrupt(); // czekamy az stana for( int i= 0; i < watki.length; i++ ) if( watki[i]!= null && watki[i]!= tenwatek ) { try { watki[i].join(); // join zglasza InterruptedException catch( InterruptedException e ) { // zlekcewaz - czekamy na "potomstwo" // zostal tylko tenwatek