concurrency java semaphore
Tento kurz bude diskutovat komponenty balíčku java.util.concurrent jako Java Semaphore, Executor Framework, ExecutorService pro implementaci Concurrency v Javě:
Z našich předchozích výukových programů Java víme, že platforma Java podporuje souběžné programování od základů. Základní jednotkou souběžnosti je vlákno a podrobně jsme probrali vlákna a multithreading v Javě.
c ++ implementace binárního vyhledávacího stromu
Od prostředí Java 5 a dále byl na platformu Java přidán balíček nazvaný „java.util.concurrent“. Tento balíček obsahuje sadu tříd a knihoven, které programátorovi usnadňují vývoj souběžných (vícevláknových) aplikací. Pomocí tohoto balíčku nemusíme psát složité třídy, protože máme připravené implementace většiny souběžných konceptů.
=> Zkontrolujte VŠECHNY výukové programy Java zde.
V tomto tutoriálu probereme různé komponenty balíčku java.util.concurrent týkající se souběžnosti a multithreadingu v Javě.
Co se naučíte:
java.util.concurrent balíček
Níže jsou uvedeny různé součásti balíčku java.util.concurrent týkající se souběžnosti a multithreadingu v Javě. Pojďme si podrobně prozkoumat jednotlivé komponenty pomocí jednoduchých příkladů programování. Některé komponenty budeme
diskutovat jsou:
- Rámec exekutora
- ExecutorService
- ThreadPool
- Vyvolatelné
- Zámky - ReentrantLock
- Semafor
- ForkJoinPool
Exekutorský rámec v Javě
Executor Framework v Javě byl vydán s vydáním JDK 5. Exekutorský rámec (java.util.concurrent.Executor) je rámec, který se skládá z komponent, které nám pomáhají efektivně zpracovávat více vláken.
Pomocí Executor Framework můžeme spouštět objekty, které jsou Runnable, opětovným použitím již existujících vláken. Nemusíme vytvářet nová vlákna pokaždé, když potřebujeme spouštět objekty.
Rozhraní Executor API odděluje nebo odděluje provádění úkolu od skutečného úkolu pomocí Vykonavatel . Exekutor je soustředěn na rozhraní Exekutora a má dílčí rozhraní, tj. ExecutorService a třída ThreadPoolExecutor.
Takže pomocí Exekutora musíme vytvořit Runnable objekty a pak je poslat exekutorovi, který je provede.
Některé z osvědčených postupů, které je třeba dodržovat při používání rámce Executor, jsou
- Měli bychom provést křížovou kontrolu a naplánovat kód, abychom zkontrolovali hlavní seznamy, abychom mohli v kódu detekovat zablokování i livelock.
- Kód Java by měl být vždy spuštěn proti nástrojům statické analýzy. Příklady nástrojů statické analýzy jsou FindBugs a PMD.
- Měli bychom nejen zachytit výjimky, ale také chyby ve vícevláknových programech.
Nyní pojďme diskutovat o komponentách Executor Framework v Javě.
Vykonavatel
Exekutor lze definovat jako rozhraní používané k reprezentaci objektu, který vykonává úkoly, které mu byly poskytnuty. Zda má být úloha spuštěna v aktuálním nebo novém vlákně, závisí na bodě, odkud bylo vyvolání vyvoláno, což dále závisí na implementaci.
Takže pomocí Exekutora můžeme oddělit úkoly od skutečného úkolu a poté je spustit asynchronně.
Provedení úkolu pomocí Exekutora však nemusí být asynchronní. Exekutoři mohou úkol také okamžitě vyvolat pomocí vyvolávacího vlákna.
Níže je uveden příklad kódu k vytvoření instance Executor:
public class Invoker implements Executor { @Override public void execute (Runnable r_interface) { r_interface.run(); } }
Jakmile je vyvolávač vytvořen, jak je uvedeno výše, můžeme jej použít k provedení úkolu následujícím způsobem.
public void execute () { Executor executor = new Invoker (); executor.execute ( () -> { //perform task }); }
Všimněte si, že pokud úkol není Exekutorem přijat, hodí RejectedExecutionException.
ExecutorService
ExecutorService (java.util.concurrent.ExecutorService) naplánuje odeslané úkoly podle dostupnosti vláken a také udržuje frontu paměti. ExecutorService funguje jako kompletní řešení pro asynchronní zpracování úkolů.
Chcete-li použít ExecutorService v kódu, vytvoříme třídu Runnable. ExecutorService udržuje fond vláken a také přiřazuje úkoly vláknům. Úkoly mohou také zařadit do fronty v případě, že vlákno není k dispozici.
Níže je uveden jednoduchý příklad ExecutorService.
import java.util.concurrent.*; public class Main { public static void main(String() args) { //create ExecutorService instance with 10 threads ExecutorService executor_Service = Executors.newFixedThreadPool(10); //assign the service to Runnable instance executor_Service.execute(new Runnable() { @Override public void run() { //print the message System.out.println('Simple Example of ExecutorService!!!'); } }); //shutdown executorService executor_Service.shutdown(); } }
Výstup
Ve výše uvedeném programu vytvoříme jednoduchou instanci ExecutorService s fondem vláken skládajícím se z 10 vláken. Poté je přiřazena instanci Runnable a spuštěna k tisku výše uvedené zprávy. Po vytištění zprávy se ExecutorService vypne.
Pool vláken
Pool podprocesů v Javě je skupina pracovních podprocesů, které lze opakovaně použít a přiřadit jim úlohy.
Fond vláken obsahuje skupinu vláken pevné velikosti. Každé vlákno je vytaženo z fondu podprocesů a poskytovatel služby mu přidělí úkol. Po dokončení přiřazené úlohy je vlákno znovu přiděleno fondu vláken.
Pool vláken je výhodný, protože nemusíme vytvářet nové vlákno pokaždé, když je úkol k dispozici, čímž se zvýší výkon. Používá se v aplikacích v reálném čase, které používají Servlet a JSP, kde se ke zpracování požadavků používají fondy vláken.
V aplikacích s více podprocesy ukládá fond podprocesů prostředky a pomáhá omezit paralelismus v rámci předdefinovaných limitů.
Níže uvedený program Java demonstruje fond vláken v Javě.
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class WorkerThreadClass implements Runnable { private String message; //thread class constructor public WorkerThreadClass(String s){ this.message=s; } //run method for thread public void run() { System.out.println(' Start: '+message); processmessage(); //sleep between start and end System.out.println(' End: '+ message); } //processmessage method => sleeps the thread for 2 sec private void processmessage() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } public class Main { public static void main(String() args) { //create a ExecutorService instance ExecutorService executor = Executors.newFixedThreadPool(5);//creating a pool of 5 threads //create thread instances and execute them for (int i = 0; i <5; i++) { Runnable workerThrd = new WorkerThreadClass('Thread_' + i); executor.execute(workerThrd);//calling execute method of ExecutorService } //shutdown ExecutorService executor.shutdown(); while (!executor.isTerminated()) { } System.out.println('Finished all threads'); } }
Výstup
Ve výše uvedených programech existuje fond vláken 5 vláken, které jsou vytvořeny pomocí metody „newFixedThreadPool“. Potom se vlákna vytvoří a přidají do fondu a přiřadí se ExecutorService k provedení.
Volatelné v Javě
Již víme, že můžeme vytvářet vlákna pomocí dvou přístupů. Jeden přístup je rozšířením třídy Thread, zatímco druhým přístupem je implementace rozhraní Runnable.
Vlákna vytvořená pomocí rozhraní Runnable však postrádají jednu funkci, tj. Nevracejí výsledek, když je vlákno ukončeno nebo run () dokončí provádění. Toto je místo, kde se do obrazu dostane rozhraní Callable.
Pomocí rozhraní Callable definujeme úkol tak, aby vracel výsledek. Může to také vyvolat výjimku. Rozhraní Callable je součástí balíčku java.util.concurrent.
Rozhraní Callable poskytuje metodu call (), která je na podobných řádcích jako metoda run () poskytovaná rozhraním Runnable s jediným rozdílem, že metoda call () vrací hodnotu a vyvolá kontrolovanou výjimku.
Metoda call () Callable interface má následující prototyp.
public Object call () throws Exception;
Protože metoda call () vrací Object, hlavní vlákno si toho musí být vědomo.
Návratová hodnota by proto měla být uložena v jiném objektu známém hlavnímu vláknu. Tomuto účelu slouží objekt „Budoucnost“. Budoucí objekt je objekt, který obsahuje výsledek vrácený vláknem. Jinými slovy, udrží výsledek, když se Callable vrátí.
Callable zapouzdřuje úkol, který by měl běžet na jiném vlákně. Budoucí objekt ukládá výsledek vrácený z jiného vlákna.
K vytvoření vlákna nelze použít Callable interface. K vytvoření vlákna potřebujeme Runnable. K uložení výsledku je nutný budoucí objekt. Java poskytuje konkrétní typ s názvem „FutureTask“, který kombinuje funkce implementací Runnable i Future.
Vytvoříme FutureTask poskytnutím konstruktoru s Callable. Tento objekt FutureTask je poté předán konstruktoru třídy Thread k vytvoření objektu Thread.
Níže je uveden program Java, který demonstruje Callable rozhraní a Future objekt. V tomto programu také používáme objekt FutureTask.
Jak již bylo zmíněno, v programu vytvoříme třídu, která implementuje Callable rozhraní s přepsanou metodou call (). V hlavní metodě vytvoříme 10 objektů FutureTask. Každý konstruktor objektu má jako argument objekt třídy Callable. Potom je objekt FutureTask přidružen k instanci vlákna.
Proto nepřímo vytvoříme vlákno pomocí Callable objektu rozhraní.
import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; //create a class implementing Callable interface class CallableDemo implements Callable { //define call () method public Object call() throws Exception { Random generator = new Random(); Integer randomNumber = generator.nextInt(10); Thread.sleep(randomNumber * 1000); return randomNumber; } } public class Main { public static void main(String() args) throws Exception { // Array of FutureTask objects FutureTask() randomNumberTasks = new FutureTask(10); for (int i = 0; i <10; i++) { Callable callable = new CallableDemo(); // Create the FutureTask with Callable class randomNumberTasks(i) = new FutureTask(callable); // create thread with FutureTask Thread t = new Thread(randomNumberTasks(i)); //start the thread t.start(); } System.out.println('The contents of FutureTask objects:'); for (int i = 0; i < 10; i++) { // get() contents of FutureTask System.out.print(randomNumberTasks(i).get() + ' '); } } }
Výstup
Jak je ukázáno ve výše uvedeném programu, metoda call () Callable, která je přepsána ve třídě implementující Callable, generuje náhodná čísla. Jakmile je vlákno spuštěno, zobrazí tato náhodná čísla.
V hlavní funkci také používáme objekty FutureTask. Protože implementuje rozhraní Future, nemusíme ukládat výsledky do objektů Thread. Podobně můžeme zrušit úkol, zkontrolovat, zda běží nebo je dokončen, a také získat výsledek pomocí objektu FutureTask.
ReentrantLock v Javě
V našem posledním kurzu jsme podrobně probrali synchronizaci vláken pomocí synchronizovaného klíčového slova. Použití synchronizovaného slova pro synchronizaci vláken je základní metodou a je poněkud rigidní.
Pomocí synchronizovaného klíčového slova lze vlákno uzamknout pouze jednou. Také poté, co jedno vlákno opustí synchronizovaný blok, další vlákno získá zámek. Neexistuje žádná čekací fronta. Tyto problémy mohou způsobit hladovění nějakého jiného vlákna, protože se nemusí dlouho dostat k prostředkům.
K řešení těchto problémů potřebujeme flexibilní metodu synchronizace vláken. „Reentrant Locks“ je tato metoda v Javě, která poskytuje synchronizaci s mnohem větší flexibilitou.
Třída „ReentrantLock“ implementuje zámky Reentrant a je součástí balíčku „import java.util.concurrent.locks“. Třída ReentrantLock poskytuje synchronizaci metody pro přístup ke sdíleným prostředkům. Třídy mají také metody zamykání a odemykání pro zamykání / odemykání prostředků při přístupu k vláknům.
Jedním zvláštním rysem ReentrantLock je, že vlákno může uzamknout sdílený prostředek více než jednou pomocí ReentrantLock. Poskytuje počet pozdržení, který je nastaven na jeden, když vlákno uzamkne prostředek.
Vlákno může před odemknutím znovu vstoupit do zdroje a přistupovat k němu. Pokaždé, když vlákno přistupuje k prostředku pomocí zámku Reentrant, počet zadržení se zvýší o jednu. Při každém odemčení se počet pozdržení sníží o jednu.
Když počet pozdržení dosáhne 0, sdílený prostředek se odemkne.
Třída ReentrantLock také poskytuje parametr spravedlnosti, což je logická hodnota, kterou lze předat konstruktoru zámku. Když je parametr spravedlnosti nastaven na hodnotu true, pak kdykoli jedno vlákno uvolní zámek, zámek se předá nejdelšímu čekajícímu vláknu. Tím se zabrání hladovění.
Zámky reentrantu lze použít následovně:
return_type method_name() { reentrantlock.lock(); try { //Do some work } catch(Exception e) { e.printStackTrace(); } finally { reentrantlock.unlock(); } }
Všimněte si, že prohlášení o odemčení pro ReentrantLock je vždy v bloku finally. To zaručuje, že zámek se uvolní, i když je vyvolána výjimka.
Pojďme implementovat program Java, abychom porozuměli ReentrantLock.
import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.*; import java.util.concurrent.locks.ReentrantLock; //thread class that implements Runnable interface class ThreadClass implements Runnable { String task_name; //define ReentrantLock object ReentrantLock thrd_lck; //ThreadClass constructor initialized lock and task name public ThreadClass(ReentrantLock r_lock, String t_name) { thrd_lck = r_lock; task_name = t_name; } //thread run () method public void run() { boolean bool_val = false; while (!bool_val) { //check for Outer Lock boolean tryLock_val = thrd_lck.tryLock(); // if lock is free, do the following if(tryLock_val) { try { for(int i=0;i<=6;i++) { if(i>=2) { thrd_lck.lock(); Thread thread_one = new Thread(); System.out.println('Thread Created.....'); if(i==3) { thread_one.setName('Maint Thread2'); System.out.println('Thread Created.....'); } } if(i==4) thrd_lck.unlock(); break; } System.out.println('ReentrantLock=>Is locked after sleep(1500) : ' + thrd_lck.isLocked()); System.out.println('Work done for task : ' + task_name ); bool_val = true; } catch(Exception e) { e.printStackTrace(); } } } } } public class Main { public static void main(String() args) { //define ReentrantLock lock object and service pool ReentrantLock reentrant_lock = new ReentrantLock(); ExecutorService pool = Executors.newFixedThreadPool(2); //create thread instance and pass lock and task name Runnable worker_thread = new ThreadClass(reentrant_lock, 'ThreadJob'); //execute the thread in exec pool pool.execute(worker_thread); //shut down the pool pool.shutdown(); } }
Výstup
Ve výše uvedeném programu jsme vytvořili vlákno a použili jsme pro něj ReentrantLock. Pomocí ReentrantLock lze přistupovat ke sdílenému prostředku.
Semafor v Javě
Další metodou synchronizace vláken je použití Semaphore. Pomocí této konstrukce zvané semafor je přístup ke sdílenému prostředku řízen pomocí čítače. Signály jsou odesílány mezi vlákny, abychom mohli střežit kritický úsek a také se vyhnout zmeškaným signálům.
Semafor lze definovat jako proměnnou, která se používá ke správě souběžných procesů synchronizací těchto procesů. Semafory se také používají k synchronizaci přístupu ke sdílenému prostředku a tím k zabránění sporům. Oprávnění dané vláknu pro přístup ke sdílenému prostředku semaforem se také nazývá povolení.
V závislosti na tom, jaké funkce vykonávají, lze semafory rozdělit do dvou typů:
# 1) Binární semafor: Binární semafor se používá k synchronizaci souběžných procesů a implementaci vzájemného vyloučení. Binární semafor předpokládá pouze dvě hodnoty, tj. 0 a 1.
# 2) Počítání semaforu: Počítací semafor má hodnotu, která udává počet procesů, které mohou vstoupit do kritické sekce. V každém okamžiku hodnota označuje maximální počet procesů, které vstupují do kritické sekce.
jaká je nejlepší aplikace pro virtuální realitu
Jak tedy semafor funguje?
Fungování semaforu lze shrnout do následujících kroků:
- Pokud počet semaforů> 0, znamená to, že vlákno má povolení pro přístup do kritické sekce, a pak je počet snížen.
- Jinak je vlákno blokováno, dokud není získáno povolení.
- Když je vlákno provedeno s přístupem ke sdílenému prostředku, povolení je uvolněno a počet semaforů je zvýšen, takže jiné vlákno může opakovat výše uvedené kroky a získat povolení.
Výše uvedené kroky práce semaforů lze shrnout v níže uvedeném vývojovém diagramu.
V Javě náš semafor nemusíme implementovat, ale poskytuje a Semafor třída, která implementuje funkčnost semaforu. Třída Semaphore je součástí java.util.concurrent balík.
Třída Semaphore poskytuje následující konstruktory, pomocí kterých můžeme vytvořit objekt semaforu:
Semaphore (int num_value) Semaphore (int num_value, boolean how)
Tady,
num_value => počáteční hodnota počtu povolení, která určuje počet vláken, která mají přístup ke sdílenému prostředku.
jak => nastavuje pořadí, ve kterém budou vlákna přidělena povolení (how = true). Pokud how = false, pak se takové pořadí nedodržuje.
Nyní implementujeme program Java, který předvede Semafor, který se používá ke správě přístupu ke sdíleným prostředkům a prevenci podmínek závodu.
import java.util.concurrent.*; //class for shared resource class SharedRes { static int count = 0; } class ThreadClass extends Thread { Semaphore sem; String threadName; public ThreadClass(Semaphore sem, String threadName) { super(threadName); this.sem = sem; this.threadName = threadName; } @Override public void run() { // Thread T1 processing if(this.getName().equals('T1')) { System.out.println('Start: ' + threadName); try { System.out.println(threadName + ' :waiting for a permit.'); // acquire the permit sem.acquire(); System.out.println(threadName + ':Acquired permit'); // access shared resource for(int i=0; i <5; i++) { SharedRes.count++; System.out.println(threadName + ': ' + SharedRes.count); Thread.sleep(10); } } catch (InterruptedException exc) { System.out.println(exc); } // Release the permit. System.out.println(threadName + ':Released the permit'); sem.release(); } // Thread T2 processing else { System.out.println('Start: ' + threadName); try { System.out.println(threadName + ':waiting for a permit.'); // acquire the lock sem.acquire(); System.out.println(threadName + ':Acquired permit'); // process the shared resource for(int i=0; i < 5; i++) { SharedRes.count--; System.out.println(threadName + ': ' + SharedRes.count); Thread.sleep(10); } } catch (InterruptedException exc) { System.out.println(exc); } // Release the permit. System.out.println(threadName + ':Released the permit.'); sem.release(); } } } public class Main { public static void main(String args()) throws InterruptedException { //create Semaphore=> #permits = 1 Semaphore sem = new Semaphore(1); // Create thread instances T1 & T2 //T1=> Increments the count; T2=> Decrements the count ThreadClass thread1 = new ThreadClass(sem, 'T1'); ThreadClass thread2 = new ThreadClass(sem, 'T2'); // start T1 & T2 thread1.start(); thread2.start(); // Wait T1 & T2 thread1.join(); thread2.join(); System.out.println('count: ' + SharedRes.count); // display final count. } }
Výstup
Tento program deklaroval třídu pro sdílený prostředek. Deklaruje také třídu vlákna, ve které máme semaforovou proměnnou, která je inicializována v konstruktoru třídy.
V přepsané metodě run () třídy Thread se provádí zpracování instance vlákna, ve kterém vlákno získá povolení, přistupuje ke sdílenému prostředku a poté povolení uvolní.
V hlavní metodě jsme deklarovali dvě instance vláken. Obě vlákna se poté spustí a poté čekají pomocí metody join. Nakonec se zobrazí počet, tj. 0, což znamená, že obě vlákna skončila se sdíleným prostředkem.
Vidlice a připojení v Javě
Rámec fork / join byl poprvé představen v prostředí Java 7. Tento rámec se skládá z nástrojů, které mohou urychlit paralelní zpracování. Využívá všechna dostupná jádra procesoru v systému a dokončí úkol. Rámec fork / join používá přístup rozděl a panuj.
Základní myšlenkou rámce Fork / Join je, že první rámec „Forks“, tj. Rekurzivně rozdělí úkol na menší jednotlivé dílčí úkoly, dokud nejsou úkoly atomické, aby je bylo možné provádět asynchronně.
Poté se úkoly „spojí“, tj. Všechny dílčí úkoly se rekurzivně spojí do jednoho úkolu nebo návratové hodnoty.
Rámec fork / join má fond vláken známých jako „ForkJoinPool“. Tento fond spravuje pracovní vlákna typu „ForkJoinWorkerThread“, čímž poskytuje efektivní paralelní zpracování.
ForkJoinPool spravuje pracovní vlákna a také nám pomáhá získat informace týkající se výkonu a stavu fondu vláken. ForkJoinPool je implementace služby „ExecutorService“, o které jsme diskutovali výše.
Na rozdíl od pracovních vláken ForkJoinPool nevytváří samostatné vlákno pro každou dílčí úlohu. Každé vlákno ve ForkJoinPool udržuje svůj deque (dvojitá fronta) pro ukládání úkolů.
Deque funguje jako vyrovnávání pracovního zatížení vlákna a provádí to pomocí „algoritmu krádeže práce“, který je popsán níže.
Algoritmus krádeže práce
Algoritmus krádeže práce můžeme definovat jednoduchými slovy jako „Pokud je vlákno volné,„ ukradni “práci rušným vláknům“.
Pracovní vlákno vždy dostane úkoly ze svého deque. Když jsou všechny úkoly v deque vyčerpány a deque je prázdný, pracovní vlákno převezme úkol z ocasu jiného deque nebo z „globální vstupní fronty“.
Tímto způsobem je minimalizována možnost podprocesů soutěžících o úkoly a také je snížen počet opakování podprocesů pro práci. Je to proto, že vlákno již získalo největší část dostupné práce a dokončilo ji.
Jak tedy můžeme použít ForkJoinPool v programu?
Obecná definice ForkJoinPool je následující:
public class ForkJoinPool extends AbstractExecutorService
Třída ForkJoinPool je součástí balíčku „java.util.concurrent“.
V prostředí Java 8 vytvoříme instanci ForkJoinPool pomocí statické metody „common-pool ()“, která poskytuje odkaz na společný fond nebo výchozí fond vláken.
ForkJoinPool commonPool = ForkJoinPool.commonPool ();
V prostředí Java 7 vytvoříme instanci ForkJoinPool a přiřadíme ji do pole třídy nástrojů, jak je znázorněno níže.
public static ForkJoinPool forkJoinPool = new ForkJoinPool(2);
Výše uvedená definice naznačuje, že fond má úroveň paralelismu 2, takže fond bude používat 2 jádra procesoru.
Pro přístup k výše uvedenému fondu můžeme uvést následující prohlášení.
ForkJoinPool forkJoinPool = PoolUtil.forkJoinPool;
Základní typ pro úlohy ForkJoinPool je „ForkJoinTask“. Měli bychom rozšířit jednu z jeho podtříd, tj. Pro void úkoly, RecursiveAction a pro úkoly, které vracejí hodnotu, RecursiveTask. Obě rozšířené třídy poskytují výpočetní metodu abstraktní metody (), ve které definujeme logiku úlohy.
Níže je uveden příklad k předvedení ForkJoinPool.
import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; //class declaration for ForkJoinPool tasks class FJPoolTask extends RecursiveAction { private long Load = 0; public FJPoolTask(long Load) { this.Load = Load; } @Override protected void compute() { //if threshold is reached, break tasks into smaller tasks List subtasks = new ArrayList(); subtasks.addAll(createSubtasks()); for(RecursiveAction subtask : subtasks){ subtask.fork(); } } //create subtasks private List createSubtasks() { List sub_tasks =new ArrayList(); FJPoolTask sub_task1 = new FJPoolTask(this.Load / 2); FJPoolTask sub_task2 = new FJPoolTask(this.Load / 2); FJPoolTask sub_task3 = new FJPoolTask(this.Load / 2); sub_tasks.add(sub_task1); sub_tasks.add(sub_task2); sub_tasks.add(sub_task3); return sub_tasks; } } public class Main { public static void main(final String() arguments) throws InterruptedException { //get count of available processors int proc = Runtime.getRuntime().availableProcessors(); System.out.println('Processors available:' +proc); //declare forkJoinPool ForkJoinPool Pool = ForkJoinPool.commonPool(); System.out.println(' Active Threads (Before invoke):' +Pool.getActiveThreadCount()); //Declare ForkJoinPool task object FJPoolTask t = new FJPoolTask(400); //submit the tasks to the pool Pool.invoke(t); System.out.println(' Active Threads (after invoke):' +Pool.getActiveThreadCount()); System.out.println('Common Pool Size :' +Pool.getPoolSize()); } }
Výstup
Ve výše uvedeném programu zjistíme počet aktivních vláken v systému před a po volání metody „invoke ()“. Metoda invoke () se používá k odeslání úkolů do fondu. Zjistili jsme také počet dostupných procesorových jader v systému.
Často kladené otázky
Otázka č. 1) Co je Java Util Concurrent?
Odpovědět: Balíček „java.util.concurrent“ je sada tříd a rozhraní poskytovaných prostředím Java, která usnadňují vývoj souběžných (vícevláknových) aplikací. Pomocí tohoto balíčku můžeme přímo používat rozhraní a třídy i API, aniž bychom museli psát naše třídy.
Otázka č. 2) Které z následujících jsou souběžné implementace přítomné v java.util. souběžný balíček?
Odpovědět: Na vysoké úrovni obsahuje balíček java.util.concurrent nástroje jako Exekutory, Synchronizátory, Fronty, Časování a Souběžné sbírky.
Otázka č. 3) Co je to budoucí Java?
Odpovědět: Objekt Future (java.util.concurrent.Future) se používá k uložení výsledku vráceného vláknem při implementaci rozhraní Callable.
Otázka č. 4) Co je bezpečné pro vlákna v Javě?
Odpovědět: Kód nebo třída bezpečná pro vlákna v Javě je kód nebo třída, kterou lze bez problémů sdílet ve vícevláknovém nebo souběžném prostředí a přináší očekávané výsledky.
Otázka č. 5) Co je synchronizovaná kolekce v Javě?
Odpovědět: Synchronizovaná kolekce je kolekce bezpečná pro vlákna. Metoda synchronizovaná kolekce () třídy java.util.Collections vrací synchronizovanou (bezpečnou) kolekci.
Závěr
S tímto tutoriálem jsme dokončili téma multi-threading a souběžnosti v Javě. O multithreadingu jsme podrobně diskutovali v našich předchozích cvičeních. Zde jsme diskutovali o souběžnosti a implementaci související se souběžností a multithreadingem, které jsou součástí balíčku java.util.concurrent.
Diskutovali jsme o dalších dvou metodách synchronizace, semaforech a ReentrantLock. Také jsme diskutovali o ForkJoinPool, který se používá k provádění úkolů, rozdělením na jednodušší úkoly a následným připojením k výsledku.
Balíček java.util.concurrent také podporuje rámec Executor a exekutory, kteří nám pomáhají spouštět vlákna. Také jsme diskutovali implementaci fondu podprocesů, která se skládá z opakovaně použitelných podprocesů, které jsou vráceny do fondu po dokončení provádění.
Diskutovali jsme o jiném rozhraní podobném Runnable, které nám také pomáhá vrátit výsledek z vlákna a Future objektu použitého k uložení získaného výsledku vlákna.
=> Dávejte pozor na jednoduchou sérii školení Java zde.
Doporučené čtení
- Thread.Sleep () - Metoda Thread Sleep () v Javě s příklady
- Implementace Java: Vytvoření a spuštění souboru Java JAR
- Základy jazyka Java: Java Syntax, třída Java a základní koncepty Java
- Virtuální stroj Java: Jak JVM pomáhá při spouštění aplikace Java
- Modifikátory přístupu v Javě - výuka s příklady
- Synchronizace Java: Co je synchronizace vláken v Javě
- Výukový program JAVA pro začátečníky: 100+ praktických výukových programů Java Video
- Celé číslo Java a třída Java BigInteger s příklady