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.
14/6

2 A mai előadás tartalma:
Többszálúság I/O

3 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 …

4 Timer I. segítségével egy párhuzamos szálat indíthatunk mely adott időközönként lefuttatja a run metódust az alosztályt a Timer osztályból kell származtatnunk meg kell valósítanunk a run metódust amikor példányosítjuk akkor létrehozunk egy új szálat is, mely a schedule metódus segítségével elindítjuk

5 Timer II. System.out.println("Time's up!"); timer.cancel();
class RemindTask extends TimerTask { public void run() System.out.println("Time's up!"); timer.cancel(); } public static void main(String args[]) System.out.println("About to schedule task."); new Reminder(5); System.out.println("Task scheduled."); import java.util.Timer; import java.util.TimerTask; public class Reminder { Timer timer; public Reminder(int seconds) timer = new Timer(); timer.schedule(new RemindTask() , seconds*1000); }

6 Timer III. az időzítésre megadhatunk konkrét időpontot is:
Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, 23); calendar.set(Calendar.MINUTE, 1); calendar.set(Calendar.SECOND, 0); Date time = calendar.getTime(); timer = new Timer(); timer.schedule(new RemindTask(), time);

7 A Timer szál leállítása
a cancel metódus meghívásával amennyiben daemon-ként futtatjuk akkor a program automatikusan, befejezi futását ha csak daemon szálak vannak (new Timer(true).). miután minden feladatát végrehajtotta, megszüntetve minden referenciát a Timer objektumra automatikusan befejezi ténykedését a System.exit metódus meghívásával az egész programból kiléphetünk

8 Példa: class RemindTask extends TimerTask import java.util.Timer; {
int numWarningBeeps = 3; public void run() if (numWarningBeeps > 0) { toolkit.beep(); System.out.println("Beep!"); numWarningBeeps--; } else { toolkit.beep(); System.out.println("Time's up!"); System.exit(0); } } } public static void main(String args[]) { System.out.println("About to schedule task."); new AnnoyingBeep(); System.out.println("Task scheduled."); } } import java.util.Timer; import java.util.TimerTask; import java.awt.Toolkit; public class AnnoyingBeep { Toolkit toolkit; Timer timer; public AnnoyingBeep() { toolkit = Toolkit.getDefaultToolkit(); timer = new Timer(); timer.schedule(new RemindTask(), 0, 1*1000); }

9 Timer, schedule schedule( TimerTask feladat, long késleltetés, long periódus) schedule( TimerTask feladat, Date időpont, long periódus) scheduleAtFixedRate(TimerTask feladat, long késleltetés, long periódus) scheduleAtFixedRate(TimerTask feladat, Date első időpont, long periódus)

10 Thread osztály a Thread osztály egy általános szálat valósít meg mely nem csinál semmit a run metódus üres a run metódus felülírásával tudunk feladatot specifikálni 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

11 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()); } }

12 Futtatás 6 Fiji 0 Jamaica 7 Fiji 0 Fiji 5 Jamaica 1 Jamaica 8 Fiji
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 public class TwoThreadsDemo { public static void main (String[] args) new SimpleThread("Jamaica").start(); new SimpleThread("Fiji").start(); }

13 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());

14 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

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

16 Á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)

17 Á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) 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

18 Á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.

19 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()); } }

20 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;

21 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)

22 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:

23 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(); }

24 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(); }

25 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

26 Szálak szinkronizálása
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

27 Zárolás synchronized 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.

28 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

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

30 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

31 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) { }

32 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);

33 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(); }

34 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

35 Ú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()");

36 Deadlock, éhezés ebédelő filozófusok
nehéz észlelni a végtelen ciklusokat célszerű olyan szabályokat alkal- mazni melyekkel liküszöbölhetőek

37 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

38 Szál csoport metódusok
ThreadGroup(Sting name) – konstruktor ThreadGroup(ThreadGroup parent ,Sting name) – konstruktor, itt az ős a parent csoport int activeCount() – a csoportban lévő aktív szálak számát adja vissza int enumerate(Thread[] list) – a csoportban lévő szálak hivatkozásait gyűjti össze TheradGroup getParent() – a szülő csoportot adja vissza void interrupt() – megszakítja minden szál munkáját

39 I/O írás, olvasás az információ írásához olvasásához csövekre van szükségünk java.io: karakter folyamok bájt folyamok

40 I/O – karakter folyamok
16 bites karakterek olvassák, írják a forrást valamilyen műveleteket végeznek rajta

41 I/O – bájt folyamok 8 bites egységek egyszerű folyamok
feladat végző folyamok

42 Fájl folyamok FileReader FileWriter FileInputStream FileOutputStream
public class Copy { public static void main(String[] args) throws IOException { File inputFile = new File("farrago.txt"); File outputFile = new File("outagain.txt"); FileReader in = new FileReader(inputFile); FileWriter out = new FileWriter(outputFile); int c; while ((c = in.read()) != -1) out.write(c); in.close(); out.close(); } FileReader FileWriter FileInputStream FileOutputStream

43 Sor folyamok (Pipe streams)
Arra szolgálnak, hogy összekössék egyik szál bemenő csatornáját a másik szál kimenő csatornájával. Az egyik szál beírja az adatokat a csatornába és nem foglalkozik vele tovább A másik kiolvassa Nem kell foglalkoznunk a szinkronizálással Metódusai: PipedReader PipedWriter PipedInputStream PipedOutputStream

44 Példa: RhymingWords ReverseThread SortThread

45 import java.io.*; public class RhymingWords { public static void main(String[] args) throws IOException { FileReader words = new FileReader("words.txt"); Reader rhymedWords = reverse(sort(reverse(words))); BufferedReader in = new BufferedReader(rhymedWords); String input; while ((input = in.readLine()) != null) System.out.println(input); in.close(); } public static Reader reverse(Reader source) throws IOException { BufferedReader in = new BufferedReader(source); PipedWriter pipeOut = new PipedWriter(); PipedReader pipeIn = new PipedReader(pipeOut); PrintWriter out = new PrintWriter(pipeOut); new ReverseThread(out, in).start(); return pipeIn; . . . folyt köv

46 public static Reader sort(Reader source) throws IOException {
BufferedReader in = new BufferedReader(source); PipedWriter pipeOut = new PipedWriter(); PipedReader pipeIn = new PipedReader(pipeOut); PrintWriter out = new PrintWriter(pipeOut); new SortThread(out, in).start(); return pipeIn; }

47 import java.io.*; public class ReverseThread extends Thread { private PrintWriter out = null; private BufferedReader in = null; public ReverseThread(PrintWriter out, BufferedReader in) { this.out = out; this.in = in; } public void run() { if (out != null && in != null) { try { String input; while ((input = in.readLine()) != null) { out.println(reverseIt(input)); out.flush(); out.close(); } catch (IOException e) { System.err.println("ReverseThread run: " + e); } … folytatás

48 private String reverseIt(String source) {
int i, len = source.length(); StringBuffer dest = new StringBuffer(len); for (i = (len - 1); i >= 0; i--) dest.append(source.charAt(i)); return dest.toString(); }

49 DataInputStream, DataOutputStream
segítségével egyszerűen tudunk más sorokba olvasni, írni egyedül nem használható mindenképpen csatolni kell egy másik csőhöz

50 import java.io.*; public class DataIODemo { public static void main(String[] args) throws IOException { DataOutputStream out = new DataOutputStream(new FileOutputStream(”a1.txt")); double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 }; int[] units = { 12, 8, 13, 29, 50 }; String[] descs = { "Java T-shirt", "Java Mug", "Duke Juggling Dolls", "Java Pin", "Java Key Chain" }; for (int i = 0; i < prices.length; i ++) { out.writeDouble(prices[i]); out.writeChar('\t'); out.writeInt(units[i]); out.writeChars(descs[i]); out.writeChar('\n'); } out.close(); … folyt köv

51 DataInputStream in = new DataInputStream(new FileInputStream(”a1
DataInputStream in = new DataInputStream(new FileInputStream(”a1.txt")); double price; int unit; StringBuffer desc; double total = 0.0; try { while (true) { price = in.readDouble(); in.readChar(); // throws out the tab unit = in.readInt(); char chr; desc = new StringBuffer(20); char lineSep = System.getProperty("line.separator").charAt(0); while ((chr = in.readChar()) != lineSep) desc.append(chr); System.out.println("You've ordered " + unit + " units of " + desc + " at $" + price); total = total + unit * price; } } catch (EOFException e) {} System.out.println("For a TOTAL of: $" + total); in.close();

52 Véletlen hozzáférésű fájlok
előfordul, hogy a fájl tartalmát nem sorban kell olvasnunk, hanem véletlen, tetszőleges sorrendben ilyen lehet egy .ZIP fájl melyben megkeressük az adott fájlt és azt kitömörítjük RandomAccessFile osztály: new RandomAccessFile("farrago.txt", "r"); new RandomAccessFile("farrago.txt", "rw"); int skipBytes(int) void seek(long) long getFilePointer()


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

Hasonló előadás


Google Hirdetések