Parallele Programmierung / Threadnocchio (Dietrich Boles)

Werbung
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
Herunterladen