Vlákna v Javě

Z MiS
(Rozdíly mezi verzemi)
Přejít na: navigace, hledání
(Vytvoření stránky.)
 
(Oprava kódu časovače, doplněn anonymní listener.)
 
(Nejsou zobrazeny 3 mezilehlé verze od 1 uživatele.)
Řádka 1: Řádka 1:
[[Category:VSE]][[Category:Informatika]][[Category:Java]]
+
[[Category:VSE]][[Category:Informatika]][[Category:Java]][[Category:Stránky s obrázky]][[Category:Programování]]
  
 
== Výhody a nevýhody práce s vlákny ==
 
== Výhody a nevýhody práce s vlákny ==
Řá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">Metodu <code>run()</code> nikdy nevoláme přímo, spustí ji třída <tt>Thread</tt> 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() &mdash; '''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>
   
 
  
== Metody třídy Thread ==
 
run()
 
*Popisuje, co má vlákno vykonávat.
 
*'''Nevolá se přímo!'''
 
start()
 
*spustí vlákno
 
 
Thread.sleep(int ''time'')
 
* Třídní metoda.
 
* Zastaví aktuální vlákno na stanovený počet milisekund.
 
* Můžeme volat kdekoli, i v programu, který vlákna nevyužívá!
 
  
  
Řá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:
  
  
== Třída Timer ==
+
== Časování &mdash; 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>.
 +
 +
; Vytvoření časovače
 +
Timer ''nazevCasovace'' = new Timer(''delkaIntervaluMs'', ''listener'');
 +
 +
; Spuštění časovače
 +
''nazevCasovace''.start();
 +
 +
; Příklady kódu
 
<div class="Priklad">
 
<div class="Priklad">
; Příprava posluchače
+
* Příprava posluchače
  class Posluchac implements ActionListener() {
+
  class Posluchac implements ActionListener {
 
     public void actionPerformed(ActionEvent e) {
 
     public void actionPerformed(ActionEvent e) {
 
       ... ''co se má pravidelně vykonat'' ...
 
       ... ''co se má pravidelně vykonat'' ...
 
     }
 
     }
 
  }
 
  }
; Spuštění časování
+
* Spuštění časování
  Timer t = new Timer(new Posluchac(), 1000);
+
  Timer t = new Timer(1000, new Posluchac());
 
  t.start();
 
  t.start();
 
</div>
 
</div>
 +
<div class="Priklad">
 +
* Můžeme samozřejmě také použít anonymní listener (od Javy 8 i&nbsp;s&nbsp;lambda notací)
 +
Timer t = new Timer(1000, (ActionEvent e) -&gt; { System.out.println("Tik!"); } );
 +
t.start();
 +
</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 &mdash; 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]

Aktuální verze z 11. 6. 2018, 08:51


Obsah

Výhody a nevýhody práce s vlákny

Výhody
Problémy
Kdy má smysl?


Implementace v Javě


Metody třídy Thread
run()
Metodu run() nikdy nevoláme přímo, spustí ji třída Thread sama při volání metody start().
start()
Thread.sleep(int time)
stop() — nedoporučuje se!!!
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
  1. 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.
  2. Vytvoříme instanci třídy Vlakno.
  3. Vytvoříme instanci třídy Thread.
    • V konstruktoru předáme instanci třídy Vlakno.
  4. 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


Modifikátor synchronized

synchronized {...}


Synchronizace kolekce

List<Prvek> data = Collections.synchronizedList(new ArrayList<Prvek>()); 
synchronized(data) {
   Iterator i = data.iterator(); // Must be in synchronized block
   while (i.hasNext())
      foo(i.next());
}


Časování — třída Timer

Vytvoření časovače
Timer nazevCasovace = new Timer(delkaIntervaluMs, listener);
Spuštění časovače
nazevCasovace.start();
Příklady kódu
  • 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(1000, new Posluchac());
t.start();
  • Můžeme samozřejmě také použít anonymní listener (od Javy 8 i s lambda notací)
Timer t = new Timer(1000, (ActionEvent e) -> { System.out.println("Tik!"); } );
t.start();


Komunikace mezi vlákny

Příklad — Pravidelný výpis stavu výpočtu

Komunikace-vlaken.png


Další informace

Osobní nástroje
Jmenné prostory
Varianty
Akce
Výuka
Navigace
Nástroje