
Edmund Richardson
0
5143
262
Vícevláknové zpracování je metoda psaní kódu pro paralelní provádění úloh. Java má vynikající podporu pro psaní vícevláknového kódu od prvních dnů Java 1.0. Nedávná vylepšení Java zvýšily způsoby, kterými lze kód strukturovat tak, aby do programů Java bylo možné začlenit více vláken.
V tomto článku porovnáme několik z těchto možností, takže můžete lépe posoudit, kterou možnost použít pro svůj další projekt Java Love GitHub? 4 důvody, proč byste měli hostit svůj kód na BitBucket Love GitHub? 4 důvody, proč byste měli hostit svůj kód na BitBucket Musíte přemýšlet o tom, kam chcete kód uložit. Pravděpodobně jste už slyšeli o GitHubu. To není překvapivé. GitHub je používán jednotlivci a podniky k hostování kódu, spolupráci na dokumentaci ... t.
Metoda 1: Rozšíření třídy vlákno
Java poskytuje Vlákno třída, kterou lze rozšířit o implementaci běh() metoda. Tato metoda run () implementuje váš úkol. Pokud chcete kopnout úkol do vlastního vlákna, můžete vytvořit instanci této třídy a vyvolat její Start() metoda. Tím se spustí provádění podprocesu a spustí se dokončení (nebo se ukončí výjimka).
Zde je jednoduchá třída vlákna, která právě spí po zadaný interval jako způsob simulace dlouhodobé operace.
public class MyThread rozšiřuje Thread private int sleepFor; public MyThread (int sleepFor) this.sleepFor = sleepFor; @Override public void run () System.out.printf ("[% s] vlákno začíná \ n", Thread.currentThread (). ToString ()); zkuste Thread.sleep (this.sleepFor); catch (InterruptedException ex) System.out.printf ("[% s] vlákno končící \ n", Thread.currentThread (). toString ());
Vytvořte instanci této třídy vlákna tím, že jí dáte počet milisekund ke spánku.
MyThread pracovník = nový MyThread (sleepFor);
Zahájení provádění tohoto pracovního vlákna vyvoláním metody start (). Tato metoda vrátí ovládání okamžitě volajícímu, aniž by čekala na ukončení vlákna.
worker.start (); System.out.printf ("[% s] hlavní vlákno \ n", Thread.currentThread (). ToString ());
A tady je výstup ze spuštění tohoto kódu. Označuje, že diagnostika hlavního vlákna je vytištěna před spuštěním pracovního vlákna.
[Závit [hlavní, 5, hlavní]] hlavní závit [Závit [Závit-0,5, hlavní]] závit začínající [Závit [Závit-0,5, hlavní]] konec závitu
Protože po spuštění pracovního vlákna již neexistují žádné příkazy, čeká hlavní vlákno na dokončení pracovního vlákna před ukončením programu. To umožňuje pracovnímu vláknu dokončit svůj úkol.
Metoda 2: Použití instance podprocesu se spustitelnou
Java také poskytuje rozhraní nazvané Runnable které lze implementovat dělnickou třídou k provedení úkolu v ní běh() metoda. Toto je alternativní způsob vytvoření dělnické třídy na rozdíl od rozšíření Vlákno třída (popsáno výše).
Zde je implementace dělnické třídy, která nyní implementuje Runnable místo rozšiřování vlákna.
public class MyThread2 implementuje Runnable // stejný jako výše
Výhodou implementace rozhraní Runnable namísto rozšíření třídy vlákno je, že dělnická třída nyní může rozšířit třídu specifickou pro doménu v hierarchii třídy.
Co to znamená?
Řekněme například, že máte Ovoce třída, která implementuje určité obecné vlastnosti ovoce. Nyní chcete implementovat Papája třída, která se specializuje na určité ovocné vlastnosti. Můžete to udělat tím, že Papája třída rozšířit Ovoce třída.
public class Fruit // fruit specifics here public class Papaya rozšiřuje Fruit // potlačuje chování specifické pro papája zde
Předpokládejme, že máte nějaký časově náročný úkol, který musí Papaya podporovat, což lze provést v samostatném vlákně. Tento případ lze vyřešit tak, že třída Papaya implementuje Runnable a poskytuje metodu run (), kde se tato úloha provádí.
public class Papaya rozšiřuje Fruit implementuje Runnable // potlačující chování specifické pro papáji zde @Override public void run () // časově náročná úloha zde.
Chcete-li zahájit pracovní podproces, vytvořte instanci dělnické třídy a při vytváření ji předejte instanci Thread. Když je vyvolána metoda start () vlákna, úloha se provede v samostatném vlákně.
Papaya papaya = nová Papaya (); // nastavte vlastnosti a vyvolejte metody papaya zde. Vlákno vlákna = nové vlákno (papája); thread.start ();
A to je stručné shrnutí toho, jak pomocí Runnable implementovat úlohu prováděnou v rámci podprocesu.
Metoda 3: Spuštění Runnable With ExecutorService
Počínaje verzí 1.5 poskytuje Java Služba ExecutorService jako nové paradigma pro vytváření a správu vláken v programu. Zobecňuje koncept provádění podprocesů tím, že abstrahuje vytváření podprocesů.
Důvodem je, že úkoly můžete spouštět v rámci skupiny podprocesů stejně snadno jako pomocí samostatného vlákna pro každou úlohu. To umožňuje programu sledovat a spravovat, kolik vláken se používá pro pracovní úkoly.
Předpokládejme, že čeká na provedení 100 pracovních úkolů. Pokud spustíte jedno vlákno na pracovníka (jak je uvedeno výše), měli byste v rámci svého programu 100 vláken, což by mohlo vést k problémům jinde v programu. Pokud místo toho použijete fond podprocesů s, řekněme 10 předběžně přidělených podprocesů, bude těchto podprocesů provedeno jedna po druhé, takže váš program nebude mít zdroje. Tyto podprocesy podprocesů lze navíc nakonfigurovat tak, aby se zavěšovaly a prováděly za vás další úkoly.
Služba ExecutorService přijímá Runnable úkol (vysvětleno výše) a spustí úlohu ve vhodnou dobu. Předložit() metoda, která přijímá úlohu Runnable, vrací instanci třídy nazvané Budoucnost, což umožňuje volajícímu sledovat stav úkolu. Zejména dostat() metoda umožňuje volajícímu čekat na dokončení úlohy (a poskytuje návratový kód, pokud existuje).
V níže uvedeném příkladu vytvoříme ExecutorService pomocí statické metody newSingleThreadExecutor (), což, jak název napovídá, vytvoří jedno vlákno pro provádění úkolů. Pokud je při spuštění jedné úlohy odesláno více úkolů, služba ExecutorService tyto úlohy zařazuje do fronty pro následné provedení.
Implementace Runnable, kterou zde používáme, je stejná jako výše popsaná.
ExecutorService esvc = Executor.newSingleThreadExecutor (); Runnable worker = new MyThread2 (sleepFor); Budoucí budoucnost = esvc.submit (pracovník); System.out.printf ("[% s] hlavní vlákno \ n", Thread.currentThread (). ToString ()); future.get (); esvc.shutdown ();
Všimněte si, že služba ExecutorService musí být řádně vypnuta, když již není třeba pro další zadávání úkolů.
Metoda 4: Vyvolatelný použit s ExecutorService
Počínaje verzí 1.5 představila Java nové rozhraní s názvem Volaný. Je to podobné staršímu runnable rozhraní s tím rozdílem, že metoda provádění (tzv.) volání() namísto běh()) může vrátit hodnotu. Kromě toho může také prohlásit, že Výjimka může být hozen.
Služba ExecutorService může také přijímat úkoly implementované jako Volaný a vrací a Budoucnost s hodnotou vrácenou metodou při dokončení.
Zde je příklad Mango třída, která rozšiřuje Ovoce třída definována dříve a implementuje Volaný rozhraní. V rámci systému se provádí nákladný a časově náročný úkol volání() metoda.
public class Mango rozšiřuje Fruit implementuje Callable public Integer call () // drahý výpočet zde vrací nový Integer (0);
A zde je kód pro odeslání instance třídy do ExecutorService. Následující kód také čeká na dokončení úkolu a vytiskne jeho návratovou hodnotu.
ExecutorService esvc = Executor.newSingleThreadExecutor (); MyCallable worker = new MyCallable (sleepFor); Budoucí budoucnost = esvc.submit (pracovník); System.out.printf ("[% s] hlavní vlákno \ n", Thread.currentThread (). ToString ()); System.out.println ("Úloha vrácena:" + future.get ()); esvc.shutdown ();
Čemu dáváš přednost?
V tomto článku jsme se naučili několik metod psaní vícevláknového kódu v Javě. Tyto zahrnují:
- Rozšíření Vlákno třída je nejzákladnější a byla k dispozici z Java 1.0.
- Pokud máte třídu, která musí rozšířit jinou třídu v hierarchii tříd, můžete implementovat Runnable rozhraní.
- Moderní zařízení pro vytváření vláken je Služba ExecutorService které mohou přijmout instanci Runnable jako úlohu, kterou chcete spustit. Výhodou této metody je, že pro provádění úkolů můžete použít fond podprocesů. Fond podprocesů pomáhá při ochraně zdrojů opakovaným používáním vláken.
- Nakonec můžete také vytvořit úkol implementací Volaný rozhraní a odeslání úlohy do služby ExecutorService.
Kterou z těchto možností si myslíte, že budete používat v dalším projektu? Dejte nám vědět v komentářích níže.