Einführung Multithreading Serialisierung Literatur Ausgewählte Implementierungsprobleme Rebecca Tiarks 18. Dezember 2008 1 / 30 Einführung Multithreading Serialisierung Literatur Inhaltsverzeichnis 1 Einführung 2 Multithreading Synchronisation 3 Serialisierung Persistenzproblem & CSV Binärformat Serialisierung 2 / 30 Einführung Multithreading Serialisierung Literatur Themenübersicht 1 18. Dez: Multithreading + Serialisierung 2 8. Jan. Swing 3 15. Jan TCP, Sockets 4 22. Jan SSL, RMI 5 29. JDBC, OR-Mapper (Hibernate, JPox, Java Persistence API, Castor, ...) 3 / 30 Einführung Multithreading Serialisierung Literatur Ablauf http://www.informatik.unibremen.de/st/Lehre/swp0809/Implementierungsprobleme/index.html 1 Beispielcode zum Ausprobieren auf der Webseite 2 Übungsblatt zu den Themen 3 Musterlösung wird online gestellt 4 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Threads und Nebenläufigkeit Nebenläufigkeit - mehrere Programme gleichzeitig Umschaltung übernimmt Scheduler des Betriebssystems aktive Programme bestehen aus Prozessen pro Prozess mind. ein Thread der Code ausführt 5 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Threads in Java wenn BS Threads unterstützt - direkte Abbildung ansonsten Abbildung durch VM Threads sind Objekte in Java verschiedene Klassen, Schnittstellen für Multithreading Thread, Runnable, Lock, Condition, ThreadGroup Erzeugung von Threads auf zwei Arten Implementierung des Interfaces java.lang.Runnable Ableiten von der Klasse Thread (die das Interface Runnable implementiert) 6 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Die Schnittstelle Runnable Was Thread tun soll wird in Runnable verpackt und Thread übergeben nur die Methode run() ist vorgeschrieben enthält Anweisungen die Parallel ausgeführt werden sollen und ist Startpunkt eines Threads zum Starten muss ein Thread-Objekt mit der Referenz auf das Runnable erzeugt werden und gestartet werden start() 7 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Beispiel class Test implements Runnable { public void run () { for ( int i = 0; i < 20; i ++ ) System . out . println ( i ); } } Erzeugen und Starten eines Thread-Objekts Thread test = new Thread ( new Test () ); test . start (); 8 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Beispiel Verbesserung: Runnable verwaltet Thread selber automatisches Starten im Konstruktor mit this-Referenz class Test implements Runnable { Test () { new Thread ( this ). start (); } public void run () { for ( int i = 0; i < 20; i ++ ) System . out . println ( i ); } } 9 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Erweitern der Klasse Thread implementiert Runnable stellt run() Methode zur Verfügung es muss kein Runnable-Exemplar mehr im Konstruktur eingefügt werden Starten durch den Aufruf von start() dadurch wird neuer Thread erzeugt und run() aufgerufen 10 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Beispiel public class Test extends Thread { public void run () { for ( int i = 0; i < 20; i ++ ) System . out . println ( i ); } } Erzeugen und Starten: Thread test = new Test ( ); test . start (); 11 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Erweitern der Klasse Thread durch Erweitern können Methoden direkt genutzt werden getName() currentThread() nur einmaliges Ableiten möglich 12 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Zustände eines Threads Neu: wurde erzeugt, aber noch nicht gestartet Lauffähig: laufend oder ausführbar Blockiert: wartend, I/O-blockiert, gesperrt, suspendiert Tot: ausführung beendet 13 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Threads schlafen legen Threads können angehalten werden Klassenfunktion Thread.sleep() (statische Funktion, keine Objektmethode ) static void sleep( long millis ) throws InterruptedException muss in einem try-catch-Block stehen da Exception ausgelöst wird. try { Thread . sleep ( 2000 ); } catch ( I nterruptedException e ) { } 14 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Prioritäten Zahl zwischen 1 und 10 Thread.MIN PRIORITY Thread.MAX PRIORITY final int getPriority() setPriority( int newPriority ) mit yield() kann ein Thread eine Runde aussetzen reiht sich in die Threadwarteschlange ein 15 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Unterbrechung Unterbrechung z.B. bei Endlosschleife interrupted(), isInterrupted(), interrupt() interrupt() setzt Flag das mit isInterrupted() abgefragt werden kann interrupted() fragt Status ab und löscht diesen sleep(), wait(), join() lösen InterruptException aus nach Unterbrechung 16 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Warten auf einen Thread Warten auf das Ende einer Aktivität (z.B. bei mehreren Threads) final void join() throws InterruptedException oder mit Zeitangabe final void join( long millis ) throws InterruptedException (wartet höchstens so lange wie angegeben) void wait () throws Exception { Thread test = new Test (); test . start (); test . join (); // warte bis Thread test terminiert } 17 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Daemon-Threads Applikation ist beendet wenn alle Threads terminiert sind Ausnahme: Daemon-Threads werden beendet wenn der letzte nicht Daemon-Thread einer Anwendung terminiert hat. final void setDaemon( boolean on ) nur vor dem Start final boolean isDaemon() 18 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Gemeinsamer Zugriff Zugriff von mehreren Threads auf gemeinsame Daten Thread kann während der Arbeit unterbrochen werden atomare Operation: arbeit während der keine Unterbrechung stattfinden kann selbst einfache Anweisungen wie i++ sind nicht atomar 19 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Gemeinsamer Zugriff in Java Monitore Baisklasse Object bietet Locks jedes Objekt hat einen Schlüssel, Thread kann Schlüssel anfordern zwei Möglichkeiten: synchronized oder mit Klassen aus java.util.concurrent.lock (seit Java 5.0) 20 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation ReentrantLock Schnittstelle Lock kritischer Abschnitt beginnt mit lock und endet mit unlock() final Lock lock = new ReentrantLock (); Runnable r = new Runnable () { public void run () { ... // tue etwas lock . lock (); // kritischer Abschnitt ... lock . unlock (); } }; 21 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation ReentrantLock ReentrantLock() erzeugt Lock-Objekt lock() und unlock() tryLock() wartet nicht sondern kehrt mit false zurück lockInterruptibly() wartet und kann unterbrochen werden zusätzlich gibt es noch die Schnittstelle ReentrantReadWriteLock 22 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation synchronized schützen von kritischen Abschnitten durch synchronized bei statischen Methoden vom Class-Objekt Thread setzt bei Objektfunktionen Monitor this-Objekts bei Blöcken keine this-Referenz deshalb Objekt anlegen class Test { private static final Object o = new Object (); static void doTest () { synchronized ( o ) { // ... } } } 23 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Benachrichtigungen Beispiel: Produzent (Clientverbindung auf dem Server) und Konsument (Verarbeiter) haben eine Liste von noch offenen Aufgaben als gemeinsame Daten. Problem: wie kann der Produzent den Konsumenten benachrichtigen, dass es neue Aufgaben gibt? Bzw. wie kann der Konsument auf neue Aufgaben warten? Thread möchte Ankommen von Informationen signalisieren andere Threads wollen Benachrichtigt werden wenn Infos da sind Idee: Abfragen in Schleife ob es neue Infos gibt 24 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation Benachrichtigungen jedes Objekt besitzt die Methoden wait() und notify() wait() gibt Lock vorübergehend frei und reiht Thread als wartend auf das Objekt ein notify(), notifyAll() wecken Threads wieder auf synchronized ( o ) { o . wait ( ) ; } synchronized ( o ) { o . notify (); // oder o . notifyAll (); } 25 / 30 Einführung Multithreading Serialisierung Literatur Synchronisation ReentrantLock ReentrantLock() repräsentiert Monitor es wird über ein gemeinsames Condition-Objekt kommuniziert newCondition() liefert Condition-Objekt kann mit await() und signal(), signalAll() kommunizieren vor dem Aufruf muss ein Bereich immer geschützt sein durch ein lock() 26 / 30 Einführung Multithreading Serialisierung Literatur Persistenzproblem & CSV Binärformat Serialisierung Persistenzproblem Anforderungen: Zeiterfassung im offline-Modus, keine Datenbank auf dem Klienten Eingaben müssen bis zur nächsten Serververbindung gespeichert werden Gewünscht ist Mechanismus der Objektstruktur und Variablenbelegung zu einer bestimmten Zeit sicher (persistent) macht und an anderer Stelle wieder hervorholt. alle Infos wie Objekttyp, Variablentyp, Unterobjekte müssen enthalten sein. Idee: eine CSV-Datei (comma seperated values) zum Schreiben java.io.PrintWriter zum Lesen java.io.BufferedReader < firstname >; < lastname >; < login >; < matrikulationNumber >; < mark > 27 / 30 Einführung Multithreading Serialisierung Literatur Persistenzproblem & CSV Binärformat Serialisierung Binärformat Probleme: bei CSV müssen die speziellen Zeichen Semikolon und Newline verhindert werden eine mögliche Lösung: URL-Format, z.B. %3B statt ; eine andere: Länge voranstellen: 6:Thomas Idee: Binärformat schreiben mit java.io.DataOutputStream, lesen mit java.io.DataInputStream für jeden Primitivtype eine readXXX() und writeXXX() Methode readUTF() und writeUTF() für Strings 28 / 30 Einführung Multithreading Serialisierung Literatur Persistenzproblem & CSV Binärformat Serialisierung Objekte Geht es einfacher? Ja! Java kennt die einzelnen Felder der Klassen auch selber Serialisierung schreiben mit java.io.ObjectOutputStream.writeObject(), lesen mit java.io.ObjectInputStream.readObject() Klassen müssen das Markierungsinterface java.io.Serializable implementieren, um zu zeigen, dass sie mit der Serialisierung einverstanden sind writeObject() bildet einen Objektgraphen auf einen Bytestrom ab alle durch das Startobjekt erreichbaren Objekte werden serialisiert → manchmal wird mehr serialisiert, als man wünscht Container wie ArrayList implementieren auch Serializable → man kann gleich den ganzen Container serialisieren 29 / 30 Einführung Multithreading Serialisierung Literatur Christian Ullenboom. Java ist auch eine Insel. Galileo Computing, 7 edition, 2008. ISBN 978-3-8362-1146-8. 30 / 30