Wykład 6. Rafał Skinderowicz

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

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

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

Programowanie współbieżne Laboratorium nr 11

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

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

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

Język Java wątki (streszczenie)

Java. Programowanie Obiektowe Mateusz Cicheński

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

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

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

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

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

Programowanie komputerów

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

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

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

Java: otwórz okienko. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Wątki w Javie. Piotr Tokarski

Multimedia JAVA. Historia

Aplikacja wielowątkowa prosty komunikator

Programowanie współbieżne i rozproszone

Kurs programowania. Wykład 8. Wojciech Macyna

Metody Metody, parametry, zwracanie wartości

Zaawansowany kurs języka Python

Język Java część 2 (przykładowa aplikacja)

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

Język Java wątki (streszczenie)

Dokumentacja do API Javy.

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

Java - wprowadzenie. Programowanie Obiektowe Mateusz Cicheński

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

Języki i metody programowania Java INF302W Wykład 2 (część 1)

Tworzenie i wykorzystanie usług

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

Programowanie obiektowe

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

Aplikacje RMI Lab4

Wprowadzenie do programowania współbieżnego. Grafika, Proste Animacje

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

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

Swing Application Framework czyli tam i z powrotem. Copyright Piotr Kochański & Erudis,

Podstawy współbieżności

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

Lista, Stos, Kolejka, Tablica Asocjacyjna

Programowanie obiektowe

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Algorytmy i Struktury Danych. Anna Paszyńska

Ćwiczenie 1. Kolejki IBM Message Queue (MQ)

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

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

Generatory. Michał R. Przybyłek

Programowanie i projektowanie obiektowe

Aplikacja wielow tkowa prosty komunikator

Wywoływanie metod zdalnych

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

Wyjątki. Streszczenie Celem wykładu jest omówienie tematyki wyjątków w Javie. Czas wykładu 45 minut.

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

Aplikacje RMI

Wykład 7: Pakiety i Interfejsy

Współbieżność w Javie

Podstawy i języki programowania

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

Task Parallel Library

Współbieżność w Javie

Programowanie obiektowe

Wykład 5. Synchronizacja (część II) Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Serwer współbieżny połączeniowy

Aplikacje RMI. Budowa aplikacji rozproszonych. Część 2.

Programowanie rozproszone w języku Java

Wywoływanie metod zdalnych

Wstęp do programowania 2

Programowanie wielowątkowe. Tomasz Borzyszkowski

Sposoby tworzenia projektu zawierającego aplet w środowisku NetBeans. Metody zabezpieczenia komputera użytkownika przed działaniem apletu.

Jak ujarzmić hydrę czyli programowanie równoległe w Javie. dr hab. Piotr Bała, prof. UW ICM Uniwersytet Warszawski

Laboratorium z przedmiotu: Inżynieria Oprogramowania INEK Instrukcja 7

Remote Method Invocation 17 listopada 2010

Java: interfejsy i klasy wewnętrzne

Programowanie graficznego interfejsu użytkownika. Wykład 8. Maciej Wołoszyn 10 maja 2006

1 Atrybuty i metody klasowe

Programowanie współbieżne Wykład 2. Iwona Kochańska

Remote Method Invocation 17 listopada Dariusz Wawrzyniak (IIPP) 1

Podejście obiektowe do budowy systemów rozproszonych

Proxy (pełnomocnik) Cel: Zastosowanie: Dostarczyć zamiennik pewnego obiektu, pozwalający kontrolować dostęp do niego.

Programowanie obiektowe. Literatura: Autor: dr inŝ. Zofia Kruczkiewicz

Platformy Programistyczne Podstawy języka Java

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

Języki i metody programowania Java. Wykład 2 (część 2)

Model pamięci. Rafał Skinderowicz

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

Podejście obiektowe do budowy systemów rozproszonych

Java RMI. Dariusz Wawrzyniak 1. Podejście obiektowe do budowy systemów rozproszonych. obiekt. interfejs. kliencka. sieć

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

Język Java część 2 (przykładowa aplikacja)

Zaawansowane programowanie w C++ (PCP)

Kurs programowania. Wykład 9. Wojciech Macyna

Dawid Gierszewski Adam Hanasko

Programowanie obiektowe zastosowanie języka Java SE

Instrukcja 2 Laboratorium z Podstaw Inżynierii Oprogramowania

Transkrypt:

Wykład 6 Rafał Skinderowicz

Plan wykładu Wykonawcy (Executors) Kolekcje synchronizowane i współbieżne Programowanie współbieżne a GUI 2

Wykonawcy w Javie Interfejs java.util.concurrent.executor pozwala na separację zadań do wykonania od mechanizmów tworzenia i uruchamiania wątków 1 public interface Executor { 2 void execute(runnable); 3 } Zamiast 1 (new Thread(zadanie)).start(); mamy 1 e.execute(zadanie); // e - obiekt klasy Executor 3

Wykonawcy w Javie Nie określamy kiedy i w jaki sposób zadanie ma zostać wykonane zależy to od konkretnej implementacji interfejsu Executor, w szczególności zadania mogą być uruchamiane kolejno w bieżącym wątku od razu, każde w osobnym wątku wykonanie asynchroniczne kolejno po jednym lub kilka jednocześnie w osobnych wątkach tworzących pulę wątków roboczych (ang. worker threads) 1 // Najprostsza implementacja 2 class DirectExecutor implements Executor { 3 public void execute(runnable r) { 4 r.run(); 5 } 6 } 4

Pule wątków W wielu aplikacjach typu serwerowego (WWW, baz danych, plików, pocztowe) istnieje konieczność wykonywania dużej liczby krótkich zadań związanych z obsługą zdalnych żądań od klientów. Naiwna implementacja tworzenie osobnego wątku dla każdego żądania, problematyczne przy dużej liczbie zadań: 5

Pule wątków W wielu aplikacjach typu serwerowego (WWW, baz danych, plików, pocztowe) istnieje konieczność wykonywania dużej liczby krótkich zadań związanych z obsługą zdalnych żądań od klientów. Naiwna implementacja tworzenie osobnego wątku dla każdego żądania, problematyczne przy dużej liczbie zadań: narzut czasowy związany z uruchamianiem i kończeniem wątków 5

Pule wątków W wielu aplikacjach typu serwerowego (WWW, baz danych, plików, pocztowe) istnieje konieczność wykonywania dużej liczby krótkich zadań związanych z obsługą zdalnych żądań od klientów. Naiwna implementacja tworzenie osobnego wątku dla każdego żądania, problematyczne przy dużej liczbie zadań: narzut czasowy związany z uruchamianiem i kończeniem wątków dodatkowe zapotrzebowanie na pamięć: pamięć dla obiektu klasy Thread dwa dodatkowe stosy wywołań, jeden dla javy, drugi dla metod natywnych (zazwyczaj w języku C) zasoby związane z natywnymi wątkami OS 5

Pule wątków W wielu aplikacjach typu serwerowego (WWW, baz danych, plików, pocztowe) istnieje konieczność wykonywania dużej liczby krótkich zadań związanych z obsługą zdalnych żądań od klientów. Naiwna implementacja tworzenie osobnego wątku dla każdego żądania, problematyczne przy dużej liczbie zadań: narzut czasowy związany z uruchamianiem i kończeniem wątków dodatkowe zapotrzebowanie na pamięć: pamięć dla obiektu klasy Thread dwa dodatkowe stosy wywołań, jeden dla javy, drugi dla metod natywnych (zazwyczaj w języku C) zasoby związane z natywnymi wątkami OS Rozwiązanie wykonywanie zadań za pomocą puli wątków roboczych o ustalonym rozmiarze 5

Pule wątków Rysunek 1: Ilustracja działania puli wątków (źródło: Cburnett CC SA 3.0) 6

Pule wątków wady Dodatkowe ryzyko zakleszczenia, jeżeli wykonywane zadania oczekują na wyniki innych zadań, które nie mogą się wykonać ze względu na ograniczony rozmiar puli Nieefektywne wykorzystanie zasobów w przypadku puli o zbyt dużych rozmiarach w stosunku do potrzeb Możliwe przeładowanie puli w przypadku zbyt wielu żądań Wyciek wątków roboczych z puli przy implementacji nieobsługującej awaryjnego kończenia zadań 7

Pule wątków wskazówki Ostrożnie z zadaniami, które czekają na wyniki innych zadań Ostrożnie z zadaniami o długim czasie wykonania np. zadania oczekujące na zakończenie operacji I/O zmniejszają niepotrzebnie wykorzystanie CPU anulowanie zadania i ponowne wstawienie do kolejki Jak właściwie dobrać rozmiar puli? Najlepsze wykorzystanie CPU, gdy rozmiar puli N = l proc Dla zadań wykonujących operacje I/O N l proc(1 + w/s), gdzie w to czas oczekiwania na zakończenie operacji I/O, s to całkowity czas wykonania zadania Profilowanie 8

Wykonawcy w Javie Za pomocą klasy Executors można tworzyć nowe obiekty wykonawców newsinglethreadexecutor() obliczenia wykonywane za pomocą dodatkowego wątku roboczego pozostałe zadania wstawiane do kolejki newfixedthreadpool(int n) obliczenia wykonywane za pomocą puli n wątków newcachedthreadpool() pula wątków o zmiennej liczebności w miarę zapotrzebowania rozszerzana o nowe wątki robocze, a w przypadku bezczynności zmniejszana newscheduledthreadpool(int n) do wykonywania zadań po upłynięciu określonego czasu lub okresowo 9

Wykonawcy w Javie Wszystkie wymienione implementacje wykonawców implementują również interfejs ExecutorService Interfejs ExecutorService rozszerza Executor o dodatkowe metody umożliwiające m.in. kończenie pracy wykonawców: shutdown() dezaktywuje wykonawcę czeka na zakończenie zleconych zadań, ale nie przyjmuje nowych shutdownnow() zatrzymuje wszystkie wykonywane zadania i anuluje wykonanie zadań oczekujących awaittermination(long timeout, TimeUnit unit) dezaktywuje wykonawcę i oczekuje na zakończenie wykonania zleconych zadań, ale nie dłużej, niż podany czas isterminated() zwraca true, jeżeli wykonawca został dezaktywowany 10

ExecutorService przykład 1 class NetworkService { 2 private final ServerSocket serversocket; 3 private final ExecutorService pool; // pula wątków roboczych 4 public NetworkService(int port, int poolsize) throws IOException { 5 serversocket = new ServerSocket(port); 6 pool = Executors.newFixedThreadPool(poolSize); 7 } 8 public void serve() { 9 try { 10 for (;;) { 11 pool.execute(new Handler(serverSocket.accept())); 12 } 13 } catch (IOException ex) { 14 pool.shutdown(); 15 } 16 } 17 } 11

ExecutorService przykład c.d. Szkielet implementacji klasy obsługującej pojedyncze połączenie 1 class Handler implements Runnable { 2 private final Socket socket; 3 Handler(Socket socket) { this.socket = socket; } 4 public void run() { 5 // tutaj obsługa żądania 6 } 7 } 12

Interfejs Callable Interfejs Runnable nie umożliwia bezpośredniego zwracania wyników obliczeń w metodzie run() Interfejs Callable<V> umożliwia zwracanie wyniku bezpośrednio, a dodatkowo metoda ta może rzucić wyjątek 1 class Callable<V> { 2 public V call() throws Exception; 3 } 13

Interfejs Callable Interfejs ExecutorService pozwala na wykonywanie zadań implementujących Callable za pomocą metody <V> Future<V> submit(callable<v> task) Wynik Callable zwracany jest przez obiekt implementujący interfejs Future 14

Interfejs Future Umożliwia asynchroniczne wykonywanie zadań (obliczeń) Czeka na zakończenie wykonania zadania i zapamiętuje jego wynik Typowy scenariusz zastosowania: klient tworzy zadanie do wykonania i przekazuje je wykonawcy klient otrzymuje referencję do obiektu implementującego Future klient wykonuje dodatkowe obliczenia, które są niezależne od wyniku zadania klient pobiera rezultat zadania z Future, jeżeli trzeba, to czeka na jego zakończenie klient wykorzystuje wynik zadania 15

Interfejs Future Metody: V get() zwraca wynik zadania czekając na jego zakończenie dostępna jest wersja z parametrem określającym maksymalny czas oczekiwania, która rzuca wyjątek TimeoutException w przypadku anulowania rzuca wyjątek CancelledException w przypadku błędu wykonania zadania rzuca wyjątek ExecutionException boolean isdone() zwraca true, jeżeli wykonanie zadania zostało zakończone lub anulowane boolean iscancelled() zwraca true, jeżeli wykonanie zadania zostało anulowane 16

Future przykład 1 interface Image { 2 byte[] getimagedata(); 3 } 4 interface Renderer { 5 Image render(byte[] imgdata); 6 } 7 class App { // przykładowe zastosowanie Future 8 void app(final byte[] imgdata) throws... { 9 final Renderer r =...; 10 FutureTask<Image> p = new FutureTask<Image>( 11 new Callable<Image>() { // Wynikiem wykonania będzie 12 Image call() { // ob. typu Callable 13 return r.render(imgdata); 14 } 15 }); 16 new Thread(p).start(); 17 dosomethingelse(); 18 display(p.get()); // czekaj jeżeli nie gotowy 19 //... 20 } 17

Future przykład 2 (J. Ponge) 1 import java.util.*; 2 import java.util.concurrent.*; 3 import static java.util.arrays.aslist; 4 public class Sums { 5 static class Sum implements Callable<Long> { 6 private final long from; 7 private final long to; 8 Sum(long from, long to) { 9 this.from = from; 10 this.to = to; 11 } 12 @Override 13 public Long call() { 14 long acc = 0; 15 for (long i = from; i <= to; i++) { 16 acc = acc + i; 17 } 18 return acc; 19 } 20 } 18

Future przykład 2 c.d. 1 public static void main(string[] args) throws Exception { 2 ExecutorService executor = Executors.newFixedThreadPool(2); 3 List <Future<Long>> results = executor.invokeall(aslist( 4 new Sum(0, 10), 5 new Sum(100, 1000), 6 new Sum(10000, 1000000) 7 )); 8 executor.shutdown(); 9 for (Future<Long> result : results) { 10 System.out.println(result.get()); 11 } 12 } 19

Fork / Join W Javie 7 dodano wykonawcę ForkJoinPool implementującego ExecutorService dla ułatwienia efektywnej implementacji algorytmów równoległych. automatyczna dystrybucja zadań między wątkami w puli jeżeli jakieś zadanie czeka na wyniki innego, to uruchamiane jest kolejne z zaplanowanych zadań (ang. work stealing) zadania powinny dziedziczyć z klasy RecursiveTask<V>, gdy zwracają wynik lub RecursiveAction, gdy nie zwracają wyniku ForkJoinPool domyślnie korzysta z tylu wątków ile jest dostępnych fizycznych rdzeni / procesorów 20

Fork / Join Schemat algorytmu nadającego się do zastosowania modelu Fork / Join 1 if (wielkość zadania jest mała) 2 policz bezpośrednio 3 else { 4 podziel zadanie na dwa podzadania 5 uruchom (invoke) podzadania i czekaj na wynik 6 połącz wyniki podzadań w wynik całego zadania 7 } Jest to przykład zastosowania strategii dziel-i-zwyciężaj 21

Fork / Join przykład 1 class Sumowanie extends RecursiveTask<Long> { 2 private final long start, koniec; 3 Sumowanie(long start, long koniec) { 4 this.start = start; 5 this.koniec = koniec; 6 } 7 @Override 8 public Long compute() { 9 long suma = 0; 10 final long Porcja = 1024; 11 if (koniec - start > Porcja) { 12 long polowa = (koniec - start) / 2; 13 Sumowanie s1 = new Sumowanie(start, start + polowa); 14 s1.fork(); // uruchom równolegle 15 Sumowanie s2 = new Sumowanie(start + polowa + 1, koniec); 16 suma = s2.compute() // oblicz zadanie s2 17 + s1.join(); // poczekaj na wynik s1 18 } else { suma = sumujbezposrednio(); } 19 return suma; 20 } 22

Fork / Join przykład c.d. 1 // Małe sumy obliczaj sekwencyjnie 2 public long sumujbezposrednio() { 3 long suma = 0; 4 for (long i = start; i <= koniec; ++i) { 5 suma += i; 6 } 7 return suma; 8 } 9 } 23

Fork / Join przykład c.d. 1 // Przykład uruchomienia zadań 2 public class ForkJoin { 3 public static void main(string [] args) { 4 ForkJoinPool forkjoinpool = new ForkJoinPool(); 5 long suma = forkjoinpool.invoke(new Sumowanie(1, 1000000)); 6 System.out.println("Suma = " + suma); 7 } 8 } 24

Strumienie Języki wysokiego poziomu mają wbudowane mechanizmy, które ułatwiają wykonywanie obliczeń w sposób równoległy bez konieczności tworzenia puli wątków w sposób jawny Java 8 zawiera API dla tzw. strumieni (ang. streams), które ułatwiają wykonywanie obliczeń na sekwencjach danych w sposób typowy dla programowania funkcyjnego Przykład zliczanie liczb pierwszych 1 int n = 10_000_000; 2 int [] numbers = new int[ n - 2 ]; 3 for (int i = 0; i < numbers.length; ++i) { 4 numbers[i] = i+2; 5 } 6 long start = System.currentTimeMillis(); 7 long count = Arrays.stream(numbers).filter(v -> isprime(v)).count(); 8 long stop = System.currentTimeMillis(); 9 System.out.printf("Number of prime numbers <= %d equals %d\n", n,count); 10 System.out.printf("Calc. time was: %d [ms]\n", stop - start); 25

Strumienie a równoległość API strumieni pozwala na łatwe zrównoleglenie obliczeń Przykład wersja sekwencyjna 1 long count = Arrays.stream(numbers).filter(v -> isprime(v)).count(); Przykład wersja równoległa 1 long count = Arrays.stream(numbers).parallel().filter(v -> isprime(v)). count(); 26

Wysokopoziomowe mechanizmy współbieżności Klasa Arrays w Javie od wersji 8 zawiera metody umożliwiające wykonywanie obliczeń równoległych na elementach tablicy, m.in. void parallelsort(int[] a, int fromindex, int toindex) <T> void parallelprefix(t[] array, BinaryOperator< T> op) Język C# udostępnia szereg wysokopoziomowych mechanizmów w bibliotece Task Paralel Library (TPL) oraz Parallel LINQ (PLINQ) 27

Kolekcje współbieżne Przed wersją 5.0 w Javie można było bezpiecznie korzystać z kolekcji synchronizowanych: Hashtable, Vector, Collections.synchronizedMap były bezpieczne, operacje wykonywane z zachowaniem wzajemnego wykluczania metody synchronizowane potencjalnie niższa wydajność niż w przypadku implementacji niewstrzymywanych (ang. lock free) oraz nieczekających (ang. wait free) Java 5.0 wprowadziła zbiór klas implementujących współbieżne kolekcje (ang. concurrent collections) większość operacji może być wykonywana jednocześnie potencjalnie dużo większa wydajność nakładanie, dowolny przeplot 28

Zastosowania kolejek w programach współbieżnych Kolejki mogą ułatwić bezpieczną komunikację między wątkami 1. Nadawca wstawia komunikat(y) do współdzielonej kolejki 2. Odbiorca w dogodnym czasie odbiera kolejny komunikat z kolejki 3. Odbiorca może wstawić do kolejki komunikat dla nadawcy 29

Zastosowania kolejek w programach współbieżnych Nie ma potrzeby dodatkowej synchronizacji cały ciężar spoczywa na metodach kolejki współbieżnej Jedna kolejka może być wykorzystywana przez wiele wątków Można utworzyć osobne kolejki dla każdej grupy / kategorii wątków / zadań Podobny schemat można zastosować dla współdzielonych zasobów 30

Kolekcje współbieżne BlockingQueue Interfejs BlockingQueue rozszerza interfejs kolejki Queue o dodatkowe metody Metoda put(e) wstawia do kolejki, wstrzymuje wątek, jeżeli w kolejce nie ma miejsca Metoda take() pobiera element z kolejki, wstrzymuje wątek, jeżeli kolejka jest pusta czeka na wstawienie nowego elementu Metoda poll(long timeout, TimeUnit u) pobiera element z kolejki, oczekując nie dłużej, niż podany czas na jego dodanie Nie ma metody, która zamyka kolejkę 31

BlockingQueue przykład 1 public class KolejkaBlokujaca { 2 public static void main(string [] args) { 3 BlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(3); 4 Producent p = new Producent(q); 5 Konsument c1 = new Konsument("1", q); 6 Konsument c2 = new Konsument("2", q); 7 new Thread(p).start(); 8 new Thread(c1).start(); 9 new Thread(c2).start(); 10 } 11 } 32

BlockingQueue przykład 1 class Konsument implements Runnable { 2 private final String id; 3 private final BlockingQueue<Integer> queue; 4 Konsument(String id, BlockingQueue<Integer> q) { 5 this.id = id; queue = q; 6 } 7 public void run() { 8 try { 9 int x = queue.take(); 10 while (x!= Integer.MAX_VALUE) { 11 konsumuj(x); 12 x = queue.take(); 13 } 14 q.put(x); // Zwróć znacznik stopu dla innych wątków 15 } catch (InterruptedException ex) { } 16 } 17 void konsumuj(integer x) { 18 System.out.printf("Konsument [%s], otrzymałem: %d\n", id, x); 19 } 20 } 33

BlockingQueue przykład 1 class Producent implements Runnable { 2 private final BlockingQueue<Integer> queue; 3 private int licznik = 0; 4 Producent(BlockingQueue<Integer> q) { queue = q; } 5 public void run() { 6 try { 7 for (int i = 0; i < 10; ++i) { queue.put(produkuj()); } 8 queue.put(integer.max_ VALUE); // Znacznik stopu 9 } catch (InterruptedException ex) { } 10 } 11 Integer produkuj() { return licznik++; } 12 } 34

Kolekcje współbieżne ConcurrentLinkedQueue Nieczekająca (ang. wait-free) implementacja kolejki Potencjalnie większa wydajność, jednak trzeba testować Uwaga na metodę size(), której złożoność nie jest O(1), ale może być O(n) wymaga przejścia po wszystkich elementach 35

Kolekcje współbieżne ConcurrentHashMap ConcurrentHashMap Zamiennik dla Hashtable oraz Collections.synchronizedMap Pozwala na jednoczesny odczyt przez kilka wątków Pozwala na zapis jednocześnie z odczytem Iteratory nie rzucają wyjątku ConcurrentModificationException Operacja odczytu get() widzi rezultaty wykonanych w całości (zakończonych) operacji modyfikacji takich jak put() i remove() Pozwala na nakładanie się domyślnie 16 operacji modyfikacji można podać więcej w parametrze konstruktora 36

Kolekcje współbieżne wydajność Rysunek 2: Porównanie skalowalności ConcurrentHashMap z HashMap. (Oś Y pokazuje liczbę operacji w jednostce czasu. Komputer: Intel i7-720qm Quad Core Hypterthreading, Hotspot JVM wersja 1.6.0 18, Windows 7. Źródło: www.javamex.com) 37

Kolekcje współbieżne CopyOnWriteArrayList Współbieżny odpowiednik ArrayList Dobra efektywność, gdy operacji odczytu jest znacznie więcej, niż operacji zapisu, ponieważ modyfikacja powoduje utworzenie kopii listy Przykładowe zastosowanie to listy odbiorców zdarzeń (ang. event listeners) 38

Kolekcje współbieżne Metody kolekcji współbieżnych wykonywane są atomowo, jednak wykonanie w sposób atomowy ciągu operacji na kolekcji wymaga synchronizacji Należy pamiętać, że metody takie jak size(), czy isempty() zwracają bieżący stan, który może stać się nieaktualny w wyniku jednoczesnej modyfikacji przez inne wątki. 39

Iteratory w kolekcjach współbieżnych Iteratory w kolekcjach synchronizowanych powodują rzucenie wyjątku ConcurrentModificationException, gdy zajdzie próba modyfikacji kolekcji podczas jej przeglądania za pomocą iteratora (ang. fast-fail mechanism) Iteratory w kolekcjach współbieżnych z java.util.concurrent nie rzucają wyjątku ConcurrentModificationException w przypadku jednoczesnej modyfikacji mogą nie zobaczyć zmian w kolekcji dokonanych podczas iterowania w najgorszym przypadku zobaczą nieaktualne dane (ang. stale data) 40

Iteratory w kolekcjach współbieżnych Ilustracja usuwania elementu z ConcurrentHashMap 41

Współbieżność a interfejs użytkownika Wielowątkowość może być pomocna w zapewnieniu płynnego działania interfejsu użytkownika (GUI) Interakcje użytkownika z GUI aplikacji generują zdarzenia Pogodzenie programowania zdarzeniowego ze współbieżnym jest trudne obie koncepcje charakteryzują się nieliniowym przebiegiem sterowania 1 Większość bibliotek GUI nie jest wielowątkowa, tj. trzeba zachować ostrożność w przypadku interakcji wątków w GUI 1 John Ousterhout. Why Threads Are A Bad Idea (for most purposes). Sun Microsystems Laboratories (1995) 42

Współbieżność a interfejs użytkownika Zazwyczaj organizacją, wyświetlaniem i obsługą GUI zajmuje się jeden, wyróżniony wątek, który zajmuje się m. in. dyspozycją zdarzeń do zarejestrowanych metod obsługi Długotrwałe obliczenia prowadzone są w wątkach roboczych, które komunikują się z wątkiem GUI W celu zapewnienia poprawnego działania programu należy pamiętać o wszystkich zasadach bezpieczeństwa, jak w przypadku każdego innego typu programu współbieżnego 43

Współbieżność GUI na przykładzie Java Swing Standardowo Java udostępnia trzy biblioteki GUI: Abstract Window Toolkit (AWT) korzysta bezpośrednio z kontrolek GUI udostępnianych przez OS Swing nowsza propozycja implementuje własne kontrolki GUI, niezależne od OS. Oferowana lista kontrolek jest bogatsza niż w przypadku AWT JavaFX zespół bibliotek i narzędzi do tworzenia aplikacji typu Rich Internet Application działających w różnych OS, przeglądarkach internetowych oraz urządzeniach mobilnych. Odpowiednik Adobe Flex, czy Microsoft Silverlight. Dostęne są również alternatywne biblioteki GUI, m.in.: SWT, Vaadin 44

Współbieżność GUI na przykładzie Java Swing Wątki w aplikacji korzystającej ze Swing można podzielić na: wątki początkowe, w tym wątek główny aplikacji inicjują tworzenie interfejsu użytkownika wątek dyspozycji zdarzeń (ang. event dispatch) obsługuje lub przekierowuje zdarzenia większość kodu obsługi zdarzeń wykonuje się w tym wątku wątki robocze szczególnie przydatne dla długotrwałych obliczeń 45

Java Swing wątki początkowe Wątek początkowy tworzy obiekt impl. Runnable odpowiedzialny za utworzenie GUI, który jest przekazywany do wątku dyspozycji zdarzeń (ang. event dispatch thread) za pomocą javax.swing.swingutilities.invokelater javax.swing.swingutilities.invokeandwait Przykład z tutoriala Swing (docs.oracle.com) 1 SwingUtilities.invokeLater(new Runnable() { 2 public void run() { 3 createandshowgui(); 4 } 5 }); 46

Java Swing wątek dyspozycji zdarzeń Zarządzaniem GUI Swing zajmuje się wątek dyspozycji zdarzeń (ang. event dispatch thread) Większość metod klas z biblioteki Swing nie może być wywoływana bezpiecznie z innych wątków bezpośrednio (nie są thread safe) Metody bezpieczne oznaczone są odpowiednio w API, np. JTextField.setText() Pętla obsługi zdarzeń Funkcje obsługi zdarzeń W celu sprawdzenia, czy bieżąca metoda wykonywana jest w wątku GUI można użyć metody javax.swing.swingutilities. iseventdispatchthread() 47

Java Swing wątek obsługi zdarzeń Obsługa zdarzeń powinna być jak najkrótsza Długotrwałe obliczenia (operacje) powinny być wykonywane w wątkach roboczych Wątki robocze mogą modyfikować elementy GUI Swing przez zlecenie zadań za pomocą metod: javax.swing.swingutilities.invokelater javax.swing.swingutilities.invokeandwait Uproszczenie komunikacji w wątkiem obsługi zdarzeń można uzyskać dzięki dziedziczeniu z klasy SwingWorker 48

Java Swing przykład 1 Przykład zastosowania SwingUtilities.invokeLater do utworzenia okna 1 public class Main { 2 public static void main(final String[] args) { 3 SwingUtilities.invokeLater(new Runnable() { 4 @Override 5 public void run() { 6 final JFrame frame = new JFrame(); 7 frame.settitle("test Frame"); 8 frame.setsize(600, 400); 9 frame.setdefaultcloseoperation(jframe.exit_on_close); 10 frame.setvisible(true); 11 } 12 }); 13 } 14 } 49

Java SwingWorker Klasa SwingWorker udostępnia łatwy interfejs dla wykonywania długotrwałych zadań w wątku roboczym i interakcji z wątkiem dyspozycji zdarzeń Obliczenia wykonywane są w metodzie doinbackground() Po zakończeniu obliczeń w wątku dyspozycji zdarzeń wykonywana jest metoda done(), która może pobrać wynik obliczeń za pomocą metody get() Krótkie obliczenia done() Wątek dyspozycji zdarzeń Czas doinbackground() Wątek roboczy (SwingWorker) Czas get() wynik 50

Java SwingWorker W celu informowania o postępie obliczeń klasa SwingWorker udostępnia metody publish w celu publikowania pośrednich wyników progress w celu przetwarzania pośrednich wyników w wątku GUI process() done() Wątek dyspozycji zdarzeń Czas publish() doinbackground() Wątek roboczy (SwingWorker) get() Czas wynik 51