Nachdenken in Aurich 2009 Threadnocchio Spielerisches Erlernen der parallelen Programmierung mit Java-Threads Dietrich Boles Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 1 Gliederung Java-Threads vor Java 5 Threads Scheduling syncronized wait-notify Java-Threads seit Java 5 Sperren Atomare Variablen Queues Nützliche Synchronisationsklassen Thread-Pools Einführung in das Arbeiten mit Threadnocchio Praktisches Arbeiten mit Threadnocchio Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 2 Java-Threads Klasse java.lang.Thread public class ThreadKlasse extends Thread { private String str; public ThreadKlasse(String s) { this.str = s; } public void run() { while (true) System.out.println(this.str); } public static void main(String[] args) { ThreadKlasse hallo = new ThreadKlasse("hallo"); ThreadKlasse dibo = new ThreadKlasse("dibo"); hallo.start(); dibo.start(); } } ( 1-threads-startrek) Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 3 Thread-Zustände blockiert deblockieren (synchronized-Ende, sleep-Ende, Thread-Ende, notify, EA-Ende, interrupt) blockieren (synchronized, sleep, join, wait, EA) zuordnen erzeugt bereit start() rechnend verdrängen, yield() Java-Praktikum Threadnocchio Sonstiges Dietrich Boles beendet Ende von run Dietrich Boles Seite 4 Scheduling static int activeCount() static int enumerate(Thread[] tarray) static Thread currentThread() Thread.State getState() // NEW, TERMINATED, WAITING, … void setPriority(int priority) // wenig sinnvoll int MIN_PRIORITY, int MAX_PRIORITY, int NORM_PRIORITY static void yield() // in Zustand bereit static void sleep(long milliSekunden) // blockieren void join() // auf Ende warten void interrupt() // sleep, join unterbrechen void setDaemon(boolean on) // Garbage-Collector Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 5 Kommunikation Kommunikation = Datenaustausch über gemeinsame Variablen bzw. Objekte möglich, da sich Threads einen gemeinsamen Adressraum teilen Probleme bei der Nutzung gemeinsamer Variablen Nicht-determinierte Ergebnisse durch Races (Wettrennen) Schreib/Schreibkonflikte Schreib/Lesekonflikte „Kritische Abschnitte“ Lösung: Synchronisation = Ordnung der Abfolge bestimmter Aktivitäten mehrerer Threads Synchronisationsarten: mehrseitige Synchronisation einseitige Synchronisation Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 6 synchronized jedes Objekt besitzt Sperre (Lock) Sperren können implizit gesetzt bzw. freigegeben werden synchronized-Anweisung: synchronized (<Objektreferenz>) // Sperr-Objekt <Anweisung> // Kritischer Abschnitt synchronized-Methoden synchronized void m() { /* krit Abschnitt */ } entspricht: void m() { synchronized (this) { /* krit Abschnitt */ } } 2-mssync-elefanten Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 7 wait-notify (1) Problem: Bestimmte Anweisungen sollen nur dann ausgeführt werden, wenn anwendungsabhängige Bedingungen erfüllt sind; ansonsten warten (und zwar nicht aktiv!) public class Object public final void public final void public final void } { wait() // passives Warten notify() // wecken (eines Threads) notifyAll() // wecken aller Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 8 wait-notify (2) synchronized (obj) { while (!bedingung) obj.wait(); } Voraussetzung: Lock von obj ist gesetzt ( synchronized) Aufrufender Thread wird blockiert Lock von obj wird frei gegeben synchronized (obj) { bedingung erfüllen; obj.notify(); } Voraussetzung: Lock von obj ist gesetzt ( synchronized) Irgendein Thread T1, der auf obj wartet, wird in den Zustand bereit versetzt (notifyAll alle) T1 muss erst wieder Lock setzen, bevor er fortfahren kann 3-essync-baby Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 9 Semaphore (1) Java: synchronized-Anweisung Nachteile: Block-gebunden Kein Hand-over-Locking möglich Thread-gebunden Exklusiv Lösung: Semaphore // Thread 1 // Thread 2 sem.p(); // kritischer Abschnitt sem.v(); sem.p(); // kritischer Abschnitt sem.v(); Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 10 Semaphore (2) public class Semaphor { private int freiePlaetze; public Semaphor(int maximalFreiePlaetze) { if (maximalFreiePlaetze < 0) this.freiePlaetze = 0; else this.freiePlaetze = maximalFreiePlaetze; } public synchronized void p() { while (this.freiePlaetze == 0) { try { this.wait(); } catch (InterruptedException exc) {} } this.freiePlaetze--; } public synchronized void v() { this.freiePlaetze++; this.notify(); } } Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 11 Semaphore (3) package java.util.concurrent; class Semaphore { // seit Java 5 public Semaphore(int permits) public Semaphore(int permits, boolean fair) public void acquire() throws InterruptedException public void acquireUninterruptibly() // p public boolean tryAcquire() public void release() // v ... } 4-semaphore-elefanten Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 12 Locks(1) synchronized: implizite Sperren Locks: explizite Sperren (seit Java 5) public interface Lock { public void lock(); public void unlock(); public Condition newCondition() } public interface Condition { public void await() throws InterruptedException public void signal() public void signalAll() } public class ReentrantLock implements Lock { ... } Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 13 Locks(2) Lock sperre = new ReentrantLock(); Condition bedingung = sperre.newCondition(); sperre.lock(); try { ... bedingung.await(); } finally { sperre.unlock(); } // auf Erfülltsein warten sperre.lock(); try { ... bedingung.signal(); // Erfülltsein signalisieren } finally { sperre.unlock(); } 5-locks-baby Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 14 ReadWriteLocks ReadWriteLocks: Lösung für Reader-Writer-Problem 2 Locks: ReadLock: mehrere Threads WriteLock: exklusive Sperre public interface ReadWriteLock { public Lock readLock() public Lock writeLock() } public class ReentrantReadWriteLock implements ReadWriteLock 6-rwlocks-elefanten Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 15 Atomare Variablen (1) Klassen für atomare Variablen der Standarddatentypen keine Sperren notwendig class Konto { int kontostand1 = 0; AtomicInteger kontostand2 = new AtomicInteger(0); synchronized int einzahlen1(int betrag) { return kontostand1 = kontostand1 + betrag; } int einzahlen2(int betrag) { return this.kontostand.addAndGet(betrag); } } Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 16 Atomare Variablen (2) package java.util.concurrent.atomic; public class AtomicInteger extends java.lang.Number { public AtomicInteger(int initialValue) public final void set(int newValue) public final int get() public final boolean compareAndSet(int exp, int update) public final int addAndGet(int delta) public final int getAndIncrement() public final int getAndDecrement() public final int getAndAdd(int delta) ... } Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 17 Queues Interfaces Queue (add, element, remove, …) BlockingQueue (put, poll, …) Deque (addFirst, addLast, …) BlockingDeque (offerFirst, offerLast, …) Klassen ArrayBlockingQueue<E> (begrenzt) LinkedBlockingQueue<E> (unbegrenzt) LinkedBlockingDeque<E> (unbegrenzt) SynchronousQueue<E> (Übergabe on-the-fly) PriorityBlockingQueue<E> (Lieferung gemäß Prioritäten) DelayQueue<E extends Delayed> (Objekte bestimmen Verweildauer) … 7-queues-baby Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 18 Exchanger Welchselseitiger Austausch von Objekten zwischen Threads package java.util.concurrent; public class Exchanger<V> { public Exchanger() public V exchange(V data) throws InterruptedException } 8-exchanger-baby (ohne Lösung) Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 19 CountDownLatch Realisierung von Count-Downs package java.util.concurrent; public class CountDownLatch { public CountDownLatch(int initCount) public void await() throws InterruptedException public void countDown() ... } 9-countdown-animals Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 20 CyclicBarrier Realisierung von Sammelpunkten package java.util.concurrent; class CyclicBarrier { public CyclicBarrier(int anzahl) public int await() throws InterruptedException, BrokenBarrierException ... } 10-barriers-animals Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 21 FutureTask Threads, die Ergebnisse liefern public interface Callable<V> { public V call() throws Exception; } public class FutureTask<V> implements Runnable { public FutureTask(Callable<V> callable) public V get() throws InterruptedException, ExecutionException // ... } Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 22 Thread-Pooling (1) Threads „auf Vorrat“ class ThreadPoolExecutor implements ExecutorService { public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) public void execute(Runnable command) ... } public class Executors { public static ExecutorService newCachedThreadPool() public static ExecutorService newFixedThreadPool(int maxThreads) // ... } Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 23 Thread-Pooling (2) int ANZAHL_AUFTRAEGE = 5; int ANZAHL_GLEICHZ_THREADS = 2; ExecutorService dienstleister = Executors .newFixedThreadPool(ANZAHL_GLEICHZ_THREADS); for (int i = 0; i < ANZAHL_AUFTRAEGE; i++) { dienstleister.execute(<Runnable.auftrag>); } dienstleister.shutdown(); Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 24 Arbeiten mit Threadnocchio Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 25 Aufgaben 1. Passt das Stück „Exchanger“ so an, dass Kauffrauen und Mütter an der Kasse Essen gegen Geld tauschen! 2. Versucht einmal, die Klasse Exchanger mit den Java-1.4Standardmechanismen selbst zu implementieren! Java-Praktikum Threadnocchio Sonstiges Dietrich Boles Dietrich Boles Seite 26