Ausgewählte Implementierungsprobleme Rebecca Tiarks 18. Dezember 2008 1 / 30
Inhaltsverzeichnis 1 2 3 Persistenzproblem & CSV Binärformat 2 / 30
Themenübersicht 1 18. Dez: + 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
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
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
Threads in Java wenn BS Threads unterstützt - direkte Abbildung ansonsten Abbildung durch VM Threads sind Objekte in Java verschiedene Klassen, Schnittstellen für 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
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
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
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
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
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
Erweitern der Klasse Thread durch Erweitern können Methoden direkt genutzt werden getname() currentthread() nur einmaliges Ableiten möglich 12 / 30
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
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 ( InterruptedException e ) { } 14 / 30
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
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
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
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
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
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
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
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
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
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
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
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
Persistenzproblem Persistenzproblem & CSV Binärformat 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
Binärformat Persistenzproblem & CSV 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
Objekte Persistenzproblem & CSV Binärformat Geht es einfacher? Ja! Java kennt die einzelnen Felder der Klassen auch selber 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 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
Christian Ullenboom. Java ist auch eine Insel. Galileo Computing, 7 edition, 2008. ISBN 978-3-8362-1146-8. 30 / 30