Vlákna v Javě
Z MiS
				
				
				(Rozdíly mezi verzemi)
				
																
				
				
								
				|  (Vytvoření stránky.) |  (Přidána komunikace mezi vlákny, upravena struktura...) | ||
| Řádka 21: | Řádka 21: | ||
| == Implementace v Javě == | == Implementace v Javě == | ||
| * Vlákno je vždy provázáno s instancí třídy <tt>Thread</tt> | * Vlákno je vždy provázáno s instancí třídy <tt>Thread</tt> | ||
| + | |||
| + | ; Metody třídy Thread | ||
| + |  run() | ||
| + | *Popisuje, co má vlákno vykonávat. | ||
| + | <div class="Varovani>Tuto metodu nikdy nevoláme přímo, spustí ji třída Thread sama při volání metody <code>start()</code>.</div> | ||
| + |  start() | ||
| + | * Vytvoří vlákno a spustí v něm kód metody <code>run()</code>. | ||
| + |  Thread.sleep(int ''time'') | ||
| + | * Třídní metoda. | ||
| + | * Zastaví ''aktuální'' vlákno, odkud je zavolána, na stanovený počet milisekund. | ||
| + | * Můžeme volat kdekoli, i v programu, který vlákna nevyužívá! | ||
| + |  stop() — '''nedoporučuje se!!!''' | ||
| + | * Pokud chceme vlákno ukončit z jiného vlákna, měli bychom připravit atribut boolean a hodnotu pravidelně testovat. | ||
| + | * Viz [[#Komunikace mezi vlákny|Komunikace mezi vlákny]] | ||
| + | <div class="Varovani">Metoda <code>stop()</code> je zastaralá (depricated) a neměla by se používat! Vlákno by mělo skončit vždy samo ve vhodný okamžik na základě ukončení metody <code>run()</code>.</div> | ||
| + | |||
| + | |||
| + | == Spuštění vlastního vlákna == | ||
| ; Postup | ; Postup | ||
| # Implementujeme v naší třídě (třeba <tt>Vlakno</tt>) rozhraní <tt>Runnable</tt>. | # Implementujeme v naší třídě (třeba <tt>Vlakno</tt>) rozhraní <tt>Runnable</tt>. | ||
| Řádka 43: | Řádka 61: | ||
|   Thread ''t'' = new Thread(''v''); |   Thread ''t'' = new Thread(''v''); | ||
| </div> | </div> | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| Řádka 63: | Řádka 69: | ||
| **Nevolejte z jiného vlákna funkce Greenfootu! | **Nevolejte z jiného vlákna funkce Greenfootu! | ||
| *ArrayList, kolekce | *ArrayList, kolekce | ||
| − | ** Lze [[#Synchronizace | zasynchronizovat]]. | + | ** Lze [[#Synchronizace kolekce | zasynchronizovat]]. | 
| *Scanner | *Scanner | ||
| Řádka 86: | Řádka 92: | ||
| − | ==  | + | == Časování — třída Timer == | 
| * V Javě více variant, například: <code>javax.swing.Timer</code>. | * V Javě více variant, například: <code>javax.swing.Timer</code>. | ||
| * S pravidelnými časovými intervaly vyvolává zadaný kód. | * S pravidelnými časovými intervaly vyvolává zadaný kód. | ||
| + | * Běží ve vlastním vlákně. | ||
| * Přidáme posluchače (''listenery'', implementují rozhraní <tt>ActionListener</tt>). | * Přidáme posluchače (''listenery'', implementují rozhraní <tt>ActionListener</tt>). | ||
| * <tt>Timer</tt> ve stanovených intervalech posílám všem posluchačům zprávu <tt>actionPerformed</tt>. | * <tt>Timer</tt> ve stanovených intervalech posílám všem posluchačům zprávu <tt>actionPerformed</tt>. | ||
| Řádka 102: | Řádka 109: | ||
|   t.start(); |   t.start(); | ||
| </div> | </div> | ||
| + | |||
| + | |||
| + | == Komunikace mezi vlákny == | ||
| + | * Měli bychom se snažit minimalizovat počet proměnných, které je potřeba používat z více vláken. | ||
| + | * Pokud používáme složitější datové struktury (kolekce,...), je třeba zajistit [[#Synchronizace kolekce | synchronizaci]]. | ||
| + | |||
| + | ; Příklad — Pravidelný výpis stavu výpočtu | ||
| + | [[Image:komunikace-vlaken.png]] | ||
| == Další informace == | == Další informace == | ||
| * [http://docs.oracle.com/javase/tutorial/essential/concurrency/threads.html Docs.Oracle.com > JavaSE > Tutorial > Essential > Concurrency > Threads] | * [http://docs.oracle.com/javase/tutorial/essential/concurrency/threads.html Docs.Oracle.com > JavaSE > Tutorial > Essential > Concurrency > Threads] | ||
Verze z 12. 2. 2015, 10:04
| Obsah | 
Výhody a nevýhody práce s vlákny
- Výhody
- Využití výkonu počítače (Za jakých okolností?)
- Oddělení nesouvisejících úkolů v aplikaci.
- Problémy
- Nutnost synchronizace + riziko uváznutí — deadlock.
- Výrazně obtížnější ladění programu!!!
- Kdy má smysl?
-  Když provádím několik relativně nezávislých činností. 
- Každá činnost může běžet v jiném jádře procesoru.
 
- Jeden kus kódu má běžet stejně rychle bez ohledu na délku zpracování jiného.
- Animace na pozadí.
- Dvě okna stejného programu.
Implementace v Javě
- Vlákno je vždy provázáno s instancí třídy Thread
- Metody třídy Thread
run()
- Popisuje, co má vlákno vykonávat.
Tuto metodu nikdy nevoláme přímo, spustí ji třída Thread sama při volání metody 
start().start()
-  Vytvoří vlákno a spustí v něm kód metody run().
Thread.sleep(int time)
- Třídní metoda.
- Zastaví aktuální vlákno, odkud je zavolána, na stanovený počet milisekund.
- Můžeme volat kdekoli, i v programu, který vlákna nevyužívá!
stop() — nedoporučuje se!!!
- Pokud chceme vlákno ukončit z jiného vlákna, měli bychom připravit atribut boolean a hodnotu pravidelně testovat.
- Viz Komunikace mezi vlákny
Metoda 
stop() je zastaralá (depricated) a neměla by se používat! Vlákno by mělo skončit vždy samo ve vhodný okamžik na základě ukončení metody run().
Spuštění vlastního vlákna
- Postup
-  Implementujeme v naší třídě (třeba Vlakno) rozhraní Runnable.
- Musíme doplnit metodu public void run().
- V metodě run() napíšeme kód, který má vlákno provádět.
 
- Vytvoříme instanci třídy Vlakno.
-  Vytvoříme instanci třídy Thread.
- V konstruktoru předáme instanci třídy Vlakno.
 
- Zavoláme metodu start() třídy Thread.
- Popis chování vlákna
class Vlakno implements Runnable {
   ...
   public void run() {
      ... co se má dělat ve vlákně ...
   }
   ...
}
- Spuštění vlákna
Vlakno v = new Vlakno(); Thread t = new Thread(v);
Z více vláken nelze používat
- Greenfoot
- Není Thread-safe!!!!
- Nevolejte z jiného vlákna funkce Greenfootu!
 
- ArrayList, kolekce
- Lze zasynchronizovat.
 
- Scanner
Modifikátor synchronized
-  Pro metodu způsobí, že metoda bude prováděna jako celek.
- Provádění metody nebude přerušeno přepnutím do jiného vlákna.
 
-  Pro blok
- Používá zámek zadaného objektu.
- Může se pak dělat jen jeden z bloků
 
synchronized {...}
Synchronizace kolekce
List<Prvek> data = Collections.synchronizedList(new ArrayList<Prvek>());
- Ale je třeba dát iteraci do synchronizovaného bloku:
synchronized(data) {
   Iterator i = data.iterator(); // Must be in synchronized block
   while (i.hasNext())
      foo(i.next());
}
Časování — třída Timer
-  V Javě více variant, například: javax.swing.Timer.
- S pravidelnými časovými intervaly vyvolává zadaný kód.
- Běží ve vlastním vlákně.
- Přidáme posluchače (listenery, implementují rozhraní ActionListener).
- Timer ve stanovených intervalech posílám všem posluchačům zprávu actionPerformed.
- Příprava posluchače
class Posluchac implements ActionListener() {
   public void actionPerformed(ActionEvent e) {
      ... co se má pravidelně vykonat ...
   }
}
- Spuštění časování
Timer t = new Timer(new Posluchac(), 1000); t.start();
Komunikace mezi vlákny
- Měli bychom se snažit minimalizovat počet proměnných, které je potřeba používat z více vláken.
- Pokud používáme složitější datové struktury (kolekce,...), je třeba zajistit synchronizaci.
- Příklad — Pravidelný výpis stavu výpočtu

