Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

Fejlett Programozási Technikák 2.

Hasonló előadás


Az előadások a következő témára: "Fejlett Programozási Technikák 2."— Előadás másolata:

1 Fejlett Programozási Technikák 2.
15/4

2 Az előző előadás tartalma
Java Virtual Machine Memória kezelés Szemét gyűjtő Hiba keresés támogatás Fordító Java nyelv alapjai Változók Operátorok, Vezérlő szerkezetek Osztályok Interfészek RTTI Reflexió Alap objektumok Csomagok JAR fájlok

3 Források New Features and Enhancements J2SE 5.0 ( ) Thinking in Java, 3rd Edition ( Error Handling with Exceptions Concurrency

4 A mai előadás tartalma:
Újdonságok az 1.5-ös Java-ban Generics Metaadatok Új ciklus Enum kezelés Statikus import Hibakezelés Egyszerű kivételek Kivétel elfogása Saját kivételek gyártása Bármely kivétel elfogása Finally Többszálúság Motiváció Szálkezelés alapjai Megosztott erőforrások kezelése Szál állapotok Együttműködés szálak között

5 Újdonságok az 1.5-ös Java-ban
Generics Fordítás időben történő típus ellenőrzés a kollekciókhoz (többek között) Metaadatok Olyan megjegyzések kódba melyek a class fájlba is bekerülnek így fejlesztő, kód generáló eszközök segítségével is olvashatóak Új ciklus Mellőzhetjük az index változókat Enum kezelés Típus biztos felsorolt típusok használata Statikus import Importálás után a statikus változókra az osztályok neve nélkül is hivatkozhatunk

6 Generics Minden bővítés (downcasting) hibalehetőségeket visz a programba Ezek futás időben derülnek ki! Generics: Extra típus információ Absztrakció a típusok felett Osztályok, Interfészek, Metódusok lehetnek paraméterezettek típusokkal Megvalósítási módok: Kód specializáció (C++ template) Kód megosztás (Java) Leggyakoribb használata: List myIntList = new LinkedList(); // 1 myIntList.add(new Integer(0)); // 2 Integer x = (Integer) myIntList.iterator().next(); // 3 List<Integer> myIntList = new LinkedList<Integer>(); // 1’ myIntList.add(new Integer(0)); //2’ Integer x = myIntList.iterator().next(); // 3’

7 Generics és altípusok Példa: Joker karakter: List<? >
List<String> ls = new ArrayList<String>(); //1 List<Object> lo = ls; //2 lo.add(new Object()); // 3 String s = ls.get(0); // 4 Joker karakter: List<? > Felülről korlátos: List<? extends Shape> Alulról korlátos: List<? super Shape> Paraméteres metódus: static <T> void fromArrayToCollection(T[] a, Collection<T> c) { for (T o : a) { c.add(o); // correct }}

8 Metaadatok Gyakran szükség van a kód mellet egyéb információra is pl.: interfész leirásra, EJB telepítés leíró, … Ez akár automatikusan is legyártható, ha a kódban megtudjuk jelölni a szükséges részeket Eddig is voltak ad-hoc megoldások: transient @deprecated Elemei: Nyelvtan Feldolgozó API Class file reprezentáció A javadoc elemeket egészítik ki Új módositó elemként használható a többi módosító elem előtt (public,…) Saját elemeket is tudunk definiálni Ha nincs adattagja akkor használatánál elhagyhatjuk a zárójeleket @AdattagNelkul public class TimeTravel { ... }

9 Példa public @interface RequestForEnhancement { int id();
String synopsis(); String engineer() default "[unassigned]"; String date(); default "[unimplemented]"; } @RequestForEnhancement( id = , synopsis = "Enable time-travel", engineer = "Mr. Peabody", date = "4/1/3007" ) public static void travelThroughTime(Date destination) { ... }

10 Új ciklus A kollekciókon történő iterálás eddig: Az új ciklussal:
for (Iterator<TimerTask> i = c.iterator(); i.hasNext(); ) i.next().cancel(); Az új ciklussal: for (TimerTask t : c) t.cancel();

11 Enum kezelés Hasonlít a C++, C# enum kezelésre de osztályként van kezelve azaz: Metódusokat, mezőket adhatunk hozzá Az Object metódusait magas szinten implementálja

12 Statikus import A statikus változókhoz szükség volt az osztály nevére is: double r = Math.cos(Math.PI * theta); Az új nyelvtan megengedi: import static java.lang.Math.*; double r = cos(PI * theta); Akkor alkalmazzuk, ha viszonylag kevés változót szeretnénk így használni, sok változó esetén olvashatatlan lesz a kód

13 Hibakezelés Java: ”A rosszul megírt program nem fog futni”
Legjobb a hibákat még futás előtt kiszűrni Nem tudunk minden hibát fordításkor kiszűrni (felhasználó, hálózat, …) A hibák nagy részét futás közben kell lekezelni úgy, hogy lehetőségünk legyen átadni a hibakezelőnek a hiba forrását is C-ben és néhány régebbi nyelvben több hibakezelési mód is elterjedt. Ezek általában flag-eket használtak a hibák jelzésére (flaggink). Probléma: Programozók: ”Hibák lehetnek de nem az én kódomban” A hibák figyelése minden egyes függvényhíváskor átláthatatlanná teszi a kódot Ilyen módon nehéz volt nagy robosztus karbantartható kódokat gyártani Nagyszámú változó (hibaállapot) Hasonló problémákat kell kezelni a programban több helyen is (cut&paste)

14 Megoldások Basic: C++: Java: on error goto
Az Ada nyelv hibakezelésén alapul Java: A C++ hibakezelésén alapul

15 Exception - Kivétel Kivétel: Olyan probléma amely megakadályozza a metódus további futását az adott környezetben. (Nem egyszerű hiba mely bekövetkezésekor az adott környezetben elegendő információnk van a normál folytatáshoz) Kivétel: Ahol a probléma jelentkezik nem feltétlenül tudjuk mit kell tennünk vele. Kivételt teszünk vele és máshol egy magasabb szinten kezeljük le. (0-val osztás) Kivétel kezelés: befejezés folytatás Hiba esetén a következőket illik megtenni: Értesíteni a felhasználót Elmenteni minden munkát Lehetővé tenni a felhasználónak a programból való kilépést

16 Típusok Throwable: Error (fordításkori és rendszer hibák) Exception
RunTimeException

17 Egyszerű kivételek Amikor kivételt dobunk:
Kivétel objektumot hozunk létre a heap memória területen a new operátorral A végrehajtás jelenlegi útvonala megszakad A kivétel objektum referenciája kikerül a jelenlegi futási környezetből A kivétel kezelő mechanizmus keresi a megfelelő helyet a folytatásra if(t == null) throw new NullPointerException();

18 Kivétel argumentum Két konstruktorunk van: Throwable ős osztály
default string argumentummal rendelkező throw new NullPointerException("t = null"); Throwable ős osztály

19 Try catch blokk A kivételt kezelnünk kell
A kód és a hibakezelés elkülönülhet Olyan nyelvekben ahol nincs kivétel kezelés minden egyes metódus hívást ilyen blokkba kellene tenni! try – catch - finally blokk try { // Code that might generate exceptions } catch(Type1 id1) { // Handle exceptions of Type1 } catch(Type2 id2) { // Handle exceptions of Type2 } catch(Type3 id3) { // Handle exceptions of Type3 }

20 Saját kivételek A JDK-ban ugyan sok kivétel van de nem tudhatják milyen igényeink lehetnek Egy meglévő kivétel osztályból kell származtatnunk Gyakran nincs konstruktor: ez esetben a fordító gyárt egyet nem tudjuk a string argumentumot használni leggyakrabban a kivétel neve elég információ (egyszerűség kívánatos, mások használhatják)

21 Példa class SimpleException extends Exception {}
public class SimpleExceptionDemo { public void f() throws SimpleException { System.out.println("Throw SimpleException from f()"); throw new SimpleException(); } public static void main(String[] args) { SimpleExceptionDemo sed = new SimpleExceptionDemo(); try { sed.f(); } catch(SimpleException e) { System.err.println("Caught it!"); }); } ///:~

22 class MyException extends Exception {
public MyException() {} public MyException(String msg) { super(msg); } } public class FullConstructors { public static void f() throws MyException { System.out.println("Throwing MyException from f()"); throw new MyException(); public static void g() throws MyException { System.out.println("Throwing MyException from g()"); throw new MyException("Originated in g()"); public static void main(String[] args) { try { f(); } catch(MyException e) { e.printStackTrace(); g(); }); } ///:~ Throwing MyException from f() MyException FullConstructors.f (.*) FullConstructors.main(.*) Throwing MyException from g() MyException: Originated in g() FullConstructors.g(.*)

23 Saját kivétel class MyException2 extends Exception { private int x;
public MyException2() {} public MyException2(String msg) { super(msg); } public MyException2(String msg, int x) { super(msg); this.x = x; } public int val() { return x; } public String getMessage() { return "Detail Message: "+ x + " "+ super.getMessage();

24 Kivétel specifikálás (checked exceptions )
Java-ban kötelező megadnunk egy-egy metódusoknál a nem kezelt kivételek listáját (többet igen de kevesebbet nem mondhatunk, RunTime kivétel) Jó ha tudják a metódusunkat használó programozók mire számíthatnak (általában nem férnek hozzá a forráshoz) void f() throws TooBig, TooSmall, DivZero {

25 Bármely kivétel kezelése
Tudunk olyan kezelőt írni amely bármely kivételt képes kezelni: Ekkor a Throwable osztály megfelelő metódusai segítségével tudunk egyéb információt megtudni String getMessage( ) String getLocalizedMessage( ) String toString( ) void printStackTrace( ) void printStackTrace(PrintStream) void printStackTrace(java.io.PrintWriter) catch(Exception e) { System.err.println("Caught an exception"); }

26 Példa public class ExceptionMethods {
public static void main(String[] args) { try { throw new Exception("My Exception"); } catch(Exception e) { System.err.println("Caught Exception"); System.err.println("getMessage():" + e.getMessage()); System.err.println("getLocalizedMessage():" + e.getLocalizedMessage()); System.err.println("toString():" + e); System.err.println("printStackTrace():"); e.printStackTrace(); } } ///:~ Caught Exception getMessage():My Exception getLocalizedMessage():My Exception toString():java.lang.Exception: My Exception printStackTrace(): java.lang.Exception: My Exception ExceptionMethods.main(.*)

27 A kivétel továbbdobása
Előfordul, hogy adott helyen nem akarjuk kezelni, hanem továbbadjuk egy magasabb szintnek (Exception) Nem veszi figyelembe az ugyanazon szinten lévő catch blokkokat Ez esetben ugyanaz a kivétel objektum kerül továbbításra (stack trace) Amennyiben az új környezetet akarjuk átadni akkor: fillInStackTrace( ) metódust kell használnunk catch(Exception e) { System.err.println("An exception was thrown"); throw e; }

28 public class Rethrowing {
public static void f() throws Exception { System.out.println("originating the exception in f()"); throw new Exception("thrown from f()"); } public static void g() throws Throwable { try { f(); } catch(Exception e) { System.err.println("Inside g(),e.printStackTrace()"); e.printStackTrace(); throw e; // 17 // throw e.fillInStackTrace(); // 18 public static void main(String[] args) throws Throwable { g(); System.err.println( "Caught in main, e.printStackTrace()"); } ///:~ originating the exception in f() Inside g(),e.printStackTrace() java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:9) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:23) Caught in main, e.printStackTrace() originating the exception in f() Inside g(),e.printStackTrace() java.lang.Exception: thrown from f() at Rethrowing.f(Rethrowing.java:9) at Rethrowing.g(Rethrowing.java:12) at Rethrowing.main(Rethrowing.java:23) Caught in main, e.printStackTrace() at Rethrowing.g(Rethrowing.java:18)

29 Kivétel láncolás Gyakran egy kivétel kezelése után létrehozunk egy új kivételt és szeretnénk megőrizni a régi kivételt is A JDK 1.4-től lehetőségünk van erre a Throwable objektum és alobjektumainak konstruktora objektum fogadására is képes (sok esetben csak initCause( ) )

30 Példa public Object setField(String id, Object value)
throws DynamicFieldsException { if(value == null) { DynamicFieldsException dfe = new DynamicFieldsException(); dfe.initCause(new NullPointerException()); throw dfe; }

31 RunTimeException if(t == null) throw new NullPointerException(); Kellemetlen lenne minden egyes referncia átadásnál figyelni, hogy null értékkű-e Nem kell ezzel foglalkoznunk mivel a java automatikusan meghívja Az ehhez hasonló kivételeket a RunTimeException osztályba fogja össze Ezeket nem szükséges a metódus fejlécében jeleznünk Amennyiben ezen hibák jelentkeznek akkor: Olyan hiba merül fel amit nem tudunk kezelni (null) Olyan hiba amelyre programozóként figyelnünk kellett volna (tömb index) Segítenek a hibakeresésben

32 Példa public class NeverCaught { static void f() {
throw new RuntimeException("From f()"); } static void g() { f(); public static void main(String[] args) { g(); } ///:~ Exception in thread "main" java.lang.RuntimeException: From f() at NeverCaught.f(NeverCaught.java:7) at NeverCaught.g(NeverCaught.java:10) at NeverCaught.main(NeverCaught.java:13)

33 Finally Mivel a program végrehajtása nem kerül vissza oda ahol a kivétel keletkezett, szeretnénk bizonyos dolgokat mindenképpen végrehajtani A szemétgyűjtő ugyan felszabadítja a memóriát előbb vagy utóbb azonban a finally determinisztikus Probléma: kivétel elveszése!

34 Példa class ThreeException extends Exception {}
public class FinallyWorks { static int count = 0; public static void main(String[] args) { while(true) { try { if(count++ == 0) throw new ThreeException(); System.out.println("No exception"); } catch(ThreeException e) { System.err.println("ThreeException"); } finally { System.err.println("In finally clause"); if(count == 2) break; // out of "while" } } ///:~ ThreeException In finally clause No exception

35 Kivétel megszorítások
Ha egy metódust felülírunk akkor csak olyan kivételeket dobhatuk melyek az ős metóduban fejlécében is definiálva voltak A dobott kivételek száma nem gyarapodhat A konstruktorkra ez nem vonatkozik

36 Probléma class VeryImportantException extends Exception {
public String toString() { return "A very important exception!"; } class HoHumException extends Exception { return "A trivial exception"; public class LostMessage { void f() throws VeryImportantException { throw new VeryImportantException(); void dispose() throws HoHumException { throw new HoHumException(); public static void main(String[] args) throws Exception { LostMessage lm = new LostMessage(); try { lm.f(); } finally { lm.dispose(); } ///:~ Probléma Exception in thread "main" A trivial exception", LostMessage.dispose(LostMessage.java:24) LostMessage.main(LostMessage.java:31)

37 Szálak - Motiváció Válaszképes felhasználói interfész
egyszerre kell több dolgot is csinálni ha ki szeretnénk lépni akkor bárhonnan kiléphessen tudjunk valamit csinálni amíg az I/O műveletek folynak több processzoros gépnél kihasználja a processzorokat virtuális CPU

38 Szál (thread) Egyszerű szekvenciális parancssor a programon belül.
Könnyűsúlyú folyamat: megosztva használja a kód és az adat szekciót csökken a ”context-switch” végrehajtási idő Segítségével egyszerre több feladatot végezhetünk: képernyő frissítés hálózat kezelés …

39 Thread osztály a Thread egy virtuális processzort valósít meg
kódot futtat adat területet használ Létrehozása: két módon tudunk szálat megvalósító osztályt definiálni: a Thread osztályból származtatva és felülírva a run metódust megvalósítva a Runnable interfészt

40 A run metódus felülírása
public class SimpleThread extends Thread { public SimpleThread(String str) { super(str); } public void run() for (int i = 0; i < 10; i++) System.out.println(i + " " + getName()); try { sleep((long)(Math.random() * 1000)); } catch (InterruptedException e) {} System.out.println("DONE! " + getName()); } }

41 Futtatás 6 Fiji 0 Jamaica 7 Fiji 0 Fiji 5 Jamaica 1 Jamaica 8 Fiji
public class TwoThreadsDemo { public static void main (String[] args) new SimpleThread("Jamaica").start(); new SimpleThread("Fiji").start(); } 6 Fiji 7 Fiji 5 Jamaica 8 Fiji 6 Jamaica 9 Fiji 7 Jamaica DONE! Fiji 8 Jamaica 9 Jamaica DONE! Jamaica 0 Jamaica 0 Fiji 1 Jamaica 1 Fiji 2 Fiji 2 Jamaica 3 Fiji 3 Jamaica 4 Jamaica 4 Fiji 5 Fiji

42 A Runnable interfész megvalósítása
public class SimpleThread implements Runnable { Thread SimpleThread; public SimpleThread(String str) { SimpleThread = new Thread(this, str);} public void start() {SimpleThread.start(); } public void run() { for (int i = 0; i < 10; i++) { System.out.println(i + " " + myThread.getName()); try { myThread.sleep((long)(Math.random() * 1000)); } catch (InterruptedException e) {} } System.out.println("DONE! " + myThread.getName());

43 Mikor melyik módot válasszuk ?
Amennyiben osztályunknak származnia kell valahonnan akkor az interfész a megoldás (pl Applet esetén) Egyébként tetszőleges

44 A szál életciklusa done sleeping blokkolt suspend sleep új resume
start futtatható wait notify run metódus kilép halott stop

45 Állapotok I. új szál runnable
amikor a new operátorral létrehozzuk még nem fut ekkor a new állapotban van runnable a megfelelő erőforrások lefoglalását, a szál adminisztrálását, a szál futását a start metódus segítségével tudjuk elindítani a new állapotból. ebben az állapotban a szál nem feltétlenül fog futni. Az operációs rendszer feladata a megfelelő futási idő biztosítása számára. a szálak közötti váltás operációs rendszer függő (pl.: solaris esetén green threads, windows esetén mindegyik szálnak egy időszelet)

46 Állapotok II. blokkolt szálak a következő módokon kerülhetnek ebbe az állapotba: a sleep() metódus eredményeként (ekkor adott ideig lesz itt, try használata kötelező) yield() segítségével az azonos prioritásúak futhatnak egyébként nem számít join() egy adott ideig, vagy az adott szál futásának végéig egy olyan művelet végrehajtása esetén mely input/output műveletekkel blokkolt és addig nem tér vissza míg ezek be nem fejeződtek a wait() metódus meghívására (másik szálnak meg kell hívnia a notify vagy notifyAll metódust) amikor olyan objektumhoz próbál hozzáférni amely zárolt a suspend() metódus meghívására (ez már elavult) a resmue() metódussal lehet visszahozni. futtatható állapotba csak úgy kerülhetnek vissza ha a blokkolást előidéző eseménynek megfelelő esemény következik be

47 Állapotok III. halott szálak a run metódus kilép
hirtelen meghal mert egy kezeletlen kivétel miatt megszűnik a run metódus a stop metódus elavult ezért ne használjuk az isAlive metódus segítségével nézhetjük meg, hogy él-e még.

48 A run metódus kezelése I.
a feladat befejezése után kilép: public void run() { for (int i = 0; i < 10; i++) System.out.println(i + " " + getName()); try { sleep((long)(Math.random() * 1000)); } catch (InterruptedException e) {} } System.out.println("DONE! " + getName()); } }

49 A run metódus kezelése II.
Figyeli, hogy ki kell-e lépnie: public void run() { Thread myThread = Thread.currentThread(); while (clockThread == myThread) { repaint(); try { Thread.sleep(1000); } catch (InterruptedException e){} } public void stop() { clockThread = null;

50 Prioritás a szálak versenyeznek a CPU használatáért
nagyobb prioritású szálak előnyben vannak a kisebb prioritású szálakkal szemben a kisebb prioritású szálak csak akkor jutnak CPU időhöz, ha a nagyobb prioritású szálak már nem tartanak igényt a CPU-ra az egyenlő prioritású szálak kezelése operációs rendszer függő win9x, WinNT… az egyenlő prioritású szálak felváltva kapnak CPU időt (időosztás) solaris az egyenlő prioritású szálak csak között csak a feladat befejezése után történik váltás (probléma az önző szálak kezelése) a setPriority() metódussal lehet beállítani egy szál prioritását (MAX_PRIOROTY=10, MIN_PRIORITY=1)

51 Példa: public class SimpleThread implements Runnable {
Thread SimpleThread; public SimpleThread(String str) { SimpleThread = new Thread(this, str); } public void start() SimpleThread.start(); public void setPriority(int i) SimpleThread.setPriority(i); public void run() { Thread myThread = Thread.currentThread(); for (int i = 0; i < 10; i++) for (int c = 0; c < ; c++); System.out.println(i + " " + SimpleThread.getName()); System.out.println("DONE! " + SimpleThread.getName()); Példa:

52 Egyforma prioritás public class ThreeThreadsTest {
0 Kolumbia 1 Kolumbia 2 Kolumbia 0 Jamaica 1 Jamaica 2 Jamaica 3 Jamaica 4 Jamaica 3 Kolumbia 4 Kolumbia 5 Kolumbia 6 Kolumbia 5 Jamaica 6 Jamaica 7 Jamaica 8 Jamaica 9 Jamaica 7 Kolumbia 8 Kolumbia 9 Kolumbia DONE! Kolumbia DONE! Jamaica public class ThreeThreadsTest { public static void main (String[] args) { SimpleThread t; SimpleThread t1; t = new SimpleThread("Jamaica"); t.setPriority(1); t1 = new SimpleThread("Kolumbia"); t1.setPriority(1); t1.start(); t.start(); }

53 Különböző prioritás public class ThreeThreadsTest {
0 Jamaica 1 Jamaica 2 Jamaica 3 Jamaica 4 Jamaica 5 Jamaica 6 Jamaica 7 Jamaica 8 Jamaica 9 Jamaica DONE! Jamaica 0 Kolumbia 1 Kolumbia 2 Kolumbia 3 Kolumbia 4 Kolumbia 5 Kolumbia 6 Kolumbia 7 Kolumbia 8 Kolumbia 9 Kolumbia DONE! Kolumbia public class ThreeThreadsTest { public static void main (String[] args) { SimpleThread t; SimpleThread t1; t = new SimpleThread("Jamaica"); t.setPriority(10); t1 = new SimpleThread("Kolumbia"); t1.setPriority(1); t1.start(); t.start(); }

54 Megjegyzés olyan szálakat kell írnunk melyek nem önzőek
az operációs rendszerek különbözőek, ha platform független programot akarunk írni akkor nekünk kell gondoskodnunk a megfelelő időosztásról a yield() metódus segítségével tudjuk egy szál futását felfüggeszteni és a CPU-t átadni egy legalább ilyen prioritású szálnak (solaris) nem minden operációs rendszer rendelkezik 10 prioritási szinttel (pl winnt 7) a szálak prioritásukat a létrehozó száltól öröklik

55 Daemon thread Háttérben fut
Amikor minden szál véget ér akkor ő is befejezi tevékenységét setDaemon() isDaemon()

56 Erőforrás megosztás Egyes feladatokat nem lehet megoldani egymástól független szálakkal (pl.: közös erőforrás használata módosítása) Hibás működéshez vezethet amennyiben nem gondoskodunk zárolásról a közös erőforrás használatakor pl.: két vagy több szál bankbetétek között végez tranzakciókat. A művelet bármikor megszakadhat (windows) és nem konzekvens állapot maradhat, amit egy másik szál felhasználhat. a problémát az adatmódosító metódus megszakíthatósága okozza

57 Példa public class AlwaysEven {
private int i; public void next() { i++; i++; } public int getValue() { return i; } public static void main(String[] args) { final AlwaysEven ae = new AlwaysEven(); new Thread("Watcher") { public void run() { while(true) { int val = ae.getValue(); if(val % 2 != 0) { System.out.println(val); System.exit(0); } } } }.start(); while(true) ae.next(); } } ///:~

58 Zárolás synchronized{} atomi műveleteket nem kell szinkronizálni
long, double esetén volatile a zárolt objektumhoz csak egy szál férhet hozzá ha egy szál használ egy zárolt objektumot és meghív egy másik szálat akkor a másik szál hozzáférhet az objektumhoz minden objektumnak van egy zárolás számlálója egy szál egyszerre több objektumot is zárolhat a szál ütemező periodikusan aktiválja a szálakat, azok melyek egy zárolt objektumra várakoznak a következő soron kívüli futási jogot kapnak. metódus zárolás synchronized x() kód blokk zárolás synchronized(objektum){} – gyorsabb működés

59 Példa public class SynchronizedEvenGenerator implements Invariant { private int i; public synchronized void next() { i++; i++; } public synchronized int getValue() { return i; } public InvariantState invariant() { int val = getValue(); if(val % 2 == 0) return new InvariantOK(); else return new InvariantFailure(new Integer(val)); } public static void main(String[] args) { SynchronizedEvenGenerator gen = new SynchronizedEvenGenerator(); new InvariantWatcher(gen, 4000); // 4-second timeout while(true) gen.next(); } } ///:~

60 wait, notify, notifyAll előfordulhat olyan eset amikor egy szál a másik akciójára vár ilyenkor mivel a közös objektumot zárolt függvényeken keresztül lehet elérni ez végtelen ciklushoz vezetne wait – ha egy szál meghívja a wait() metódust akkor az objektum felszabadul és a szál blokkolva lesz amíg az adott objektumnál egy másik szál meg nem a hívja a notify, notifyAll metódust érdemes a notifyAll metódust használni mivel a másik a blokkolt szálak közül csak egyet szabadít fel azt is véltelenszerűen

61 Példa: Tároló objektum: Tarolo Adat forrás: Producer
Adat nyelő: Consumer main: PTest

62 Tarolo.java public class Tarolo {
private int contents; private boolean available = false; public synchronized int get() { while (available == false) { try { wait(); } catch (InterruptedException e) { } } System.out.println("Olvasgatok"); available = false; notifyAll(); return contents; public synchronized void put(int value) while (available == true) { System.out.println("Irogatok"); contents = value; available = true; notifyAll(); Tarolo.java

63 public class Producer extends Thread {
private Tarolo tarolo; private int number; public Producer(Tarolo c, int number) { tarolo = c; this.number = number; } public void run() { for (int i = 0; i < 10; i++) { tarolo.put(i); System.out.println("Producer #" + this.number + " beirtam: " + i); try { sleep((int)(Math.random() * 100)); } catch (InterruptedException e) { }

64 public class Consumer extends Thread {
private Tarolo tarolo; private int number; public Consumer(Tarolo c, int number) { tarolo = c; this.number = number; } public void run() { int value = 0; for (int i = 0; i < 10; i++) { value = tarolo.get(); System.out.println("Consumer #" + this.number + " kiolvastam: " + value);

65 Main public class PTest { public static void main(String[] args) {
Tarolo c = new Tarolo(); Producer p1 = new Producer(c, 1); Consumer c1 = new Consumer(c, 1); c1.start(); p1.start(); }

66 Eredmény H:\>java PTest Irogatok Olvasgatok
Consumer #1 kiolvastam: 0 Producer #1 beirtam: 0 …. Producer #1 beirtam: 8 Consumer #1 kiolvastam: 8 Producer #1 beirtam: 9 Consumer #1 kiolvastam: 9

67 Újrafoglalás public class Reentrant { public synchronized void a() {
System.out.println("here I am, in a()"); } public synchronized void b() { System.out.println("here I am, in b()");

68 Szál csoportok a szálakat csoportokba tudjuk foglalni
a csoportokon egyszerre tudunk műveleteket végrehajtani egy szál a létrehozásakor helyezhető egy csoportba, ezután már nem mozdítható el ha nem adunk meg mást akkor automatikusan a szülő szál csoportjába kerül új csoportokat létrehozása esetén az új csoport a szülő csoport gyerek csoportja lesz

69 A mai előadás tartalma:
Újdonságok az 1.5-ös Java-ban Generics Metaadatok Új ciklus Enum kezelés Statikus import Hibakezelés Egyszerű kivételek Kivétel elfogása Saját kivételek gyártása Bármely kivétel elfogása Finally Többszálúság Motiváció Szálkezelés alapjai Megosztott erőforrások kezelése Szál állapotok Együttműködés szálak között

70 A következő előadás tartalma
ANT JUnit CVS Log4J


Letölteni ppt "Fejlett Programozási Technikák 2."

Hasonló előadás


Google Hirdetések