Przykład użycia iteratora dla zbioru. Który z poniższych przykładów jest poprawny i dlaczego?

Podobne dokumenty
Programowanie współbieżne Laboratorium nr 12

Programowanie współbieżne Laboratorium nr 11

Programowanie obiektowe

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

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

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

Programowanie w języku Java. Kolekcje

Dawid Gierszewski Adam Hanasko

Programowanie współbieżne Laboratorium nr 14. Synchronizatory

Programowanie Obiektowe (Java)

TimeUnit.SECONDS.sleep(1); } } catch (InterruptedException e) { System.out.println("INTERRUPT " + System.nanoTime() + " " + isinterrupted()); }

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

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

java.util.* :Kolekcje Tomasz Borzyszkowski

Realizacja ekstensji klasy. Paulina Strzelecka, Tomasz Roszkowski

Java. Programowanie Obiektowe Mateusz Cicheński

Java Collections Framework

Podstawy współbieżności

Kurs programowania. Wykład 9. Wojciech Macyna

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

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

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

Język Java wątki (streszczenie)

Platformy Programistyczne Podstawy języka Java

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

Kolekcje - pakiet Java Collections Framework

Java SE Laboratorium nr 7. Temat: Kolekcje

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

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

Programowanie i projektowanie obiektowe

Podstawy otwartych języków programowania Przechowywanie danych

Programowanie obiektowe

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

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

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

Laboratorium z przedmiotu: Inżynieria Oprogramowania INEK Instrukcja 7

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

Wydział Fizyki i Informatyki Stosowanej, Uniwersytetu Łódzkiego Łódź. Java podstawy języka, wykład 4 1

Kolekcje - pakiet Java Collections Framework

Współbieżność w Javie

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

Język Java wątki (streszczenie)

Współbieżność w Javie

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

TYPY GENERYCZNE (GENERICS)

Wykład 2 Wybrane konstrukcje obiektowych języków programowania (1)

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

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

Systemy Rozproszone - Ćwiczenie 6

Programowanie obiektowe

Dokumentacja do API Javy.

Instrukcja 2 Laboratorium z Podstaw Inżynierii Oprogramowania

Lista, Stos, Kolejka, Tablica Asocjacyjna

Comparable<Klasa_uzytkownika>

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

Programowanie komputerów

Wątki w Javie. Piotr Tokarski

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

Java niezbędnik programisty spotkanie nr 8. Kolekcje c.d.

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

Java: interfejsy i klasy wewnętrzne

Programowanie i projektowanie obiektowe

Java Zadanie 1. Aby poprawnie uruchomić aplikację desktopową, należy zaimplementować główną metodę zapewniającą punkt wejścia do programu.

Algorytmy i Struktury Danych. Anna Paszyńska

Kolekcje w Javie cz. 1

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Programowanie w Javie- wykład 11 Kolekcje (listy)

Języki i metody programowania Java Lab4 podejście obiektowe, zastosowanie pojemników

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

Programowanie w Javie - wykład 13 Kolekcje c.d. ( mapy)

import java.util.*; public class ListExample { public static void main(string args[]) { List<String> lista1= new ArrayList<String> ();

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

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

Tworzenie aplikacji w języku Java

Plan wykładu CORBA. Cechy aplikacji rozproszonych. Aplikacje rozproszone

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)?

API STREAM WYRAŻENIA LAMBDA

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

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

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

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

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

Algorytmy i Struktury Danych.

Model pamięci. Rafał Skinderowicz

Wywoływanie metod zdalnych

Wykład 6. Rafał Skinderowicz

Klasy i obiekty cz II

Podejście obiektowe do budowy systemów rozproszonych

Remote Method Invocation 17 listopada Dariusz Wawrzyniak (IIPP) 1

Aplikacja wielowątkowa prosty komunikator

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

Kurs programowania. Wykład 8. Wojciech Macyna

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

Programowanie obiektowe

1. Czynności przygotowujące aplikację działającą na platformie Java SE Biblioteka5 (należy ją pobrać z załącznika z p.1)

Programowanie obiektowe

Wykład 4. Klasa List Kolejki Stosy Słowniki

Kolekcje mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

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

Transkrypt:

Programowanie współbieżne Laboratorium nr 13 Kolekcje a współbieżność "Iteratory szybko zgłaszające problem [1] nie zostały zaprojektowane do zapewniania poprawności w każdej sytuacji - mają za zadanie szybko wykryć błędy współbieżności i je zgłosić. Implementuje się je w taki sposób by sprawdzały licznik modyfikacji kolekcji: jeżeli licznik ulegnie zmianie w trakcie iteracji, metody hasnext() lub next() zgłoszą wyjątek ConcurrentModificationException. Niestety sprawdzanie wartości nie jest synchronizowane, więc istnieje ryzyko widzenia nieświeżej wartości modyfikacji licznika, więc występuje pewne prawdopodobieństwo niezauważenia modyfikacji." Przykład użycia iteratora dla zbioru. Który z poniższych przykładów jest poprawny i dlaczego? Set<Integer> set = new HashSet<Integer>(new Integer(10)); set.addall(arrays.aslist(new Integer[]{9,8,7,6,5,4,3,2,1,0)); for (Integer i : set) if(i % 2 == 1) set.remove(i); for (Integer i : set) System.out.print(i + ", "); Set<Integer> set = new HashSet<Integer>(new Integer(10)); set.addall(arrays.aslist(new Integer[] {9,8,7,6,5,4,3,2,1,0)); for (Iterator<Integer> it = set.iterator(); it.hasnext();) if (it.next() % 2 == 1) it.remove(); for (Integer i : set) System.out.print(i + ", "); Klasa java.util.collections: - public static final List EMPTY_LIST, - public static final Map EMPTY_MAP, - public static final Set EMPTY_SET, niezmienna pusta lista, mapa, zbiór, - public static final <T> List<T> emptylist() - public static final <K,V> Map<K,V> emptymap(), - public static final <T> Set<T> emptyset(), zwraca niezmienną pustą: listę, mapę, zbiór,

- public static <T> Collection<T> unmodifiablecollection(collection<? extends T> c), - public static <T> List<T> unmodifiablelist(list<? extends T> list), - public static <K,V> Map<K,V> unmodifiablemap( Map<? extends K,? extends V> m), - public static <T> Set<T> unmodifiableset(set<? extends T> s), - public static <K,V> SortedMap<K,V> unmodifiablesortedmap(sortedmap<k,? extends V> m), - public static <T> SortedSet<T> unmodifiablesortedset(sortedset<t> s) zwraca niemodyfikowalny widok na podaną: kolekcję, listę, mapę, zbiór, posortowaną mapę, posortowany zbiór, - public static <T> Collection<T> synchronizedcollection(collection<t> c), - public static <T> List<T> synchronizedlist(list<t> list), - public static <K,V> Map<K,V> synchronizedmap(map<k,v> m), - public static <T> Set<T> synchronizedset(set<t> s), - public static <K,V> SortedMap<K,V> synchronizedsortedmap(sortedmap<k,v> m), - public static <T> SortedSet<T> synchronizedsortedset(sortedset<t> s) zwraca synchronizowaną: kolekcję, listę, mapę, zbiór, posortowaną mapę, posortowany zbiór. Przykład niemodyfikowalnego widoku na zbiór. Które z poniższych operacji są dozwolone? Set<Integer> collection = new HashSet<Integer>( Arrays.asList(new Integer[] { 1, 2, 3 )); Collection<Integer> unmodifiablecollection = Collections.unmodifiableCollection(collection); System.out.println("UnmodifiableCollection " + unmodifiablecollection); System.out.println(" Collection " + collection); Iterator<Integer> it = unmodifiablecollection.iterator(); while (it.hasnext()) { it.next(); it.remove(); catch (Exception e) { System.out.println("UnmodifiableCollection: Exception"); e.printstacktrace(system.out); Iterator<Integer> it = collection.iterator(); while (it.hasnext()) { it.next(); it.remove(); catch (Exception e) { System.out.println(" Collection: Exception"); e.printstacktrace(); System.out.println("UnmodifiableCollection " + unmodifiablecollection); System.out.println(" Collection " + collection);

Podczas iterowania kolekcji [8] zwróconej z metody Collections.synchronizedXXX() należy wykonać ręczną synchronizację. "Implementacja metody tostring() [1] w standardowych kolekcjach przechodzi przez wszystkie elementy kolekcji i wywołuje ich metodę tostring(), (...)." "Iteracja [1] często zostaje pośrednio wykonana przez metody hashcode() i equals() kolekcji, które mogą zostać wywołane, gdy kolekcja znajduje się we wnętrzu innej kolekcji. Metody containsall(), removeall(), retainall() i konstruktory przyjmujące kolekcje również stosują iteracje." Przykład synchronizowanej listy: final private static int SIZE = 4; public static void main(string[] args) throws InterruptedException { ExecutorService e = Executors.newCachedThreadPool(); for (int i = 0; i < SIZE; i++) e.execute(new Lotto()); e.shutdown(); e.awaittermination(1, TimeUnit.DAYS); synchronized(lotto.numbers){ System.out.println(Lotto.numbers); class Lotto implements Runnable { private static List<Integer> privatenumbers = new ArrayList<Integer>(); static List<Integer> numbers = Collections.synchronizedList(privateNumbers); @Override public void run() { int i = 0; while (i < 10) { ++i; synchronized (numbers) { if (numbers.contains(i) == false) numbers.add(i); Kolekcje bezpieczne wątkowo [2]: "W pakiecie java.util.concurrent znajdują się następujące szybkie implementacje map, zbiorów uporządkowanych i kolejek:" - public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable, - public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V> implements ConcurrentNavigableMap<K,V>, Cloneable, Serializable, - public class ConcurrentSkipListSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, Serializable, - public class ConcurrentLinkedQueue<E> extends AbstractQueue<E> implements Queue<E>, Serializable.

"Kolekcje te [2] zwracają tak zwane słabo spójne iteratory (ang. weakly consistent iterators). Oznacza to, że mogą one (choć nie muszą) odzwierciedlać wszystkie modyfikacje dokonane po ich skonstruowaniu. Nie zwracają one jednak dwukrotnie wartości i nie zgłaszają wyjątku ConcurrentModificationException." Klasa ConcurrentHashMap podczas blokowania wykorzystuje algorytm zwany blokowaniem paskowym [1]. "(...) implementacja ConcurrentHashMap używa tablicy 16 blokad. Każda z nich chroni 1 / 16 tablicy mieszającej. Kubełek N chroni blokada N mod 16. Zakładając, że funkcja mieszająca mniej więcej po równo rozkłada obiekty w tablicy na podstawie kluczy, każda blokada jest16-krotnie mniej obciążona." Interfejs ConcurrentMap: - V putifabsent(k key, V value) Jeżeli podany klucz nie jest odwzorowany na żadną wartość to odwzoruj go na podaną wartość. Równoważne z atomowym wykonaniem [8]: if (!map.containskey(key)) return map.put(key, value); else return map.get(key); - boolean remove(object key, Object value) Usuwa wpis dla klucza jeżeli klucz jest on odwzorowany na podaną wartość. Równoważne z atomowym wykonaniem [8]: if (map.containskey(key) && map.get(key).equals(value)) { map.remove(key); return true; else return false; - V replace(k key, V value) Zastępuje wpis dla klucza jeżeli klucz jest odwzorowany na jakąś wartość. Równoważne z atomowym wykonaniem [8]: if (map.containskey(key)) { return map.put(key, value); else return null; - boolean replace(k key, V oldvalue, V newvalue) Zastępuje wpis dla klucza jeżeli jest on odwzorowany na podaną wartość. Równoważne z atomowym wykonaniem [8]: if (map.containskey(key) && map.get(key).equals(oldvalue)) { map.put(key, newvalue); return true; else return false;

Tablice kopiowane przy zapisie [2] "CopyOnWriteArrayList i CopyOnWriteArraySet to bezpieczne wątkowo kolekcje, których mutatory tworzą kopie tablic. Taki sposób działania sprawdza się w sytuacjach, w których liczba wątków iterujących po kolekcji znacznie przewyższa liczbę wątków ją modyfikujących. Utworzony iterator zawiera referencję do aktualnej tablicy. Jeżeli tablica ta zostanie później zmodyfikowana, iterator ten nadal będzie miał starą tablicę, mimo że tablica kolekcji jest zamieniona. Dzięki temu starszy iterator dysponuje spójnym (choć potencjalnie przestarzałym) widokiem, do którego ma dostęp nieobciążony żadnym narzutem synchronizacji." Który z poniższych przykładów wykona się poprawnie i dlaczego? List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); Iterator<Integer> it = list.iterator(); while(it.hasnext()){ System.out.print(it.next() + ", "); list.add(3); catch (Exception e) { e.printstacktrace(system.out); System.out.println(); for (int i : list) System.out.print(i + ", "); List<Integer> list = new CopyOnWriteArrayList<Integer>(); list.add(1); list.add(2); Iterator<Integer> it = list.iterator(); while(it.hasnext()){ System.out.print(it.next() + ", "); list.add(3); catch (Exception e) { e.printstacktrace(system.out); System.out.println(); for (int i : list) System.out.print(i + ", ");

Kolejki blokujące public interface BlockingQueue<E> extends Queue<E> Sposoby postępowania w przypadku wywołania operacji, która nie może być wykonana natychmiast. Na podstawie: Dokumentacja JavaDoc 1.6 Zgłasza wyjątek Zwraca specjalną wartość Blokuje się Blokuje się na określony czas Wprowadź (Insert) add(e) offer(e) put(e) offer(e, time, unit) Usuń (Remove) remove() poll() take() poll(time, unit) Sprawdź (Examine) element() peek() - - Implementacje BlockingQueue: - public class ArrayBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, Serializable, - public class DelayQueue<E extends Delayed> extends AbstractQueue<E> implements BlockingQueue<E>, - public class LinkedBlockingDeque<E> extends AbstractQueue<E> implements BlockingDeque<E>, Serializable, - public class PriorityBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, Serializable, - public class SynchronousQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, Serializable. public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> Sposoby postępowania w przypadku wywołania operacji, która nie może być wykonana natychmiast. Na podstawie: Dokumentacja JavaDoc 1.6 Pierwszy element Zgłasza wyjątek Zwraca specjalną wartość Blokuje się Blokuje się na określony czas Wprowadź (Insert) addfirst(e) offerfirst(e) putfirst(e) offerfirst(e, time, unit) Usuń (Remove) removefirst() pollfirst() takefirst() pollfirst(time, unit) Sprawdź (Examine) getfirst() peekfirst() - - Ostatni element Zgłasza wyjątek Zwraca specjalną wartość Blokuje się Blokuje się na określony czas Wprowadź (Insert) addlast(e) offerlast(e) putlast(e) offerlast(e, time, unit) Usuń (Remove) removelast() polllast() takelast() polllast(time, unit) Sprawdź (Examine) getlast() peeklast() - - Implementacja BlockingQueue: - public class LinkedBlockingDeque<E> extends AbstractQueue<E> implements BlockingDeque<E>, Serializable.

Przykład użycia LinkedBlockingQueue: class Producer implements Runnable { private boolean sleep; private int i; Producer(boolean sleep){ this.sleep = sleep; @Override public void run() { while (true) produce(); catch (InterruptedException e) { e.printstacktrace(); final void produce() throws InterruptedException { System.out.println("> " + ++i); TestCollections.queue.put(i); System.out.println(">> " + i); if(sleep) TimeUnit.SECONDS.sleep(2); class Consumer implements Runnable { private boolean sleep; private int i; Consumer(boolean sleep){ this.sleep = sleep; @Override public void run() { while (true) consume(); catch (InterruptedException e) { e.printstacktrace(); final void consume() throws InterruptedException { System.out.println("< " + ++i); int tmp = TestCollections.queue.take(); System.out.println("<< " + i + ":" + tmp); if(sleep) TimeUnit.SECONDS.sleep(2); static LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(4); public static void main(string[] args) throws Exception { new Thread(new Producer(false)).start(); new Thread(new Consumer(true)).start();

Inne kolekcje bezpieczne wątkowo [2]: - java.util.vector<e>, - java.util.hashtable<k,v>. Przykładowa treść laboratorium: 1. Stworzyć aplikacje składające się z kilku wątków zapisujących i odczytujący dane przechowywane w zbiorach: - HashSet z własną synchronizacją wykorzystującą metody lub bloki synchronizowane, - Collections.synchronizedSet(new HashSet()), - ConcurrentSkipListSet, - CopyOnWriteArraySet. 2. Stworzyć aplikację symulującą działanie konserwatora budynku. W budynku mieszka kilka osób, modelowanych jako wątki. Każda z nich co jakiś czas sprawdza stan swojego mieszkania (np. co 10 sekundę) i wykrywa awarię z podanym prawdopodobieństwem (np. 0,1). Konserwator modelowany jest także jako wątek. Do komunikacji pomiędzy mieszkańcami a konserwatorem należy zastosować klasę implementującą kolejkę blokującą BlockingQueue. Każdy z mieszkańców, który zauważy awarię zgłasza ją, czyli dodaje ją do kolejki blokującej. Konserwator pobiera opis awarii z kolejki i naprawia ją. Każda naprawa zajmuje czas (np. losowo wybrany od 1 do 5 sekund). Jeżeli nie ma zgłoszeń awarii konserwator czeka. Należy przetestować działanie aplikacji dla różnych wartości: liczby osób, odstępu pomiędzy sprawdzeniami czy wystąpiła awaria, prawdopodobieństwa awarii oraz zakresu czasu naprawy. Literatura: [1] Goetz B., Peierls T., Bloch J., Bowbeer J., Holmes D., Lea D., Java Współbieżność dla praktyków, Helion 2007 [2] Horstmann C.S., Cornell G., Java Podstawy, Helion, Wyd. VIII, 2009 [3] Horstmann C.S., Cornell G., Java Techniki zaawansowane, Helion, Wyd. VIII, 2009 [4] Eckel B.: Thinking in Java, Wyd. IV, Helion, 2006. [5] Bloch J.: Java Efektywne programowanie, Wyd. II, Helion, 2009. [6] Brackeen D., B. Barker, L. Vanhelsuwe: Java Tworzenie gier, Helion, 2004. [7] Silberschatz A., Galvin P. B., Gagne G.: Podstawy systemów operacyjnych, WNT, 2005 [8] Dokumentacja JavaDoc 1.6 htp://java.sun.com [9] Dokumentacja JavaDoc 1.7 htp://java.sun.com [10] The Java Language Specification, Third Edition, http://java.sun.com/docs/books/jls/download/langspec-3.0.pdf