concurrency java semaphore
Denna handledning diskuterar komponenter i java.util.concurrent-paketet som Java Semaphore, Executor Framework, ExecutorService för att implementera Concurrency i Java:
Från våra tidigare Java-handledning vet vi att Java-plattformen stöder samtidig programmering från grunden. Grundenheten för samtidighet är en tråd och vi har diskuterat trådar och multitrådning i Java i detalj.
Från och med Java 5 lades ett paket som heter 'java.util.concurrent' till Java-plattformen. Detta paket innehåller en uppsättning klasser och bibliotek som gör det lättare för programmeraren att utveckla samtidiga (flertrådade) applikationer. Med hjälp av det här paketet behöver vi inte skriva komplexa klasser eftersom vi har färdiga implementeringar av de flesta samtidiga koncept.
=> Kontrollera ALLA Java-handledning här.
I denna handledning kommer vi att diskutera de olika komponenterna i paketet java.util.concurrent angående samtidighet och multithreading i Java.
Vad du kommer att lära dig:
java.util.concurrent Package
Nedan listas de olika komponenterna i java.util.concurrent-paketet om samtidighet och multithreading i Java. Låt oss utforska varje komponent i detalj med hjälp av enkla programmeringsexempel. Några av komponenterna kommer vi att göra
diskutera är:
- Executor ramverk
- ExecutorService
- ThreadPool
- Callable
- Lås - ReentrantLock
- Semafor
- ForkJoinPool
Executor Framework I Java
Executor Framework i Java släpptes med JDK 5-utgåvan. Executor Framework (java.util.concurrent.Executor) är ett ramverk som består av komponenter som hjälper oss att effektivt hantera flera trådar.
Med hjälp av Executor Framework kan vi köra objekt som kan köras genom att återanvända de redan existerande trådarna. Vi behöver inte skapa nya trådar varje gång vi behöver köra objekt.
Executor API separerar eller avkopplar körningen av en uppgift från den faktiska uppgiften med hjälp av en Testamentsexekutor . En exekutör är centrerad på Executor-gränssnittet och har delgränssnitt, dvs. ExecutorService och klassen ThreadPoolExecutor.
Således använder vi Executor, vi måste bara skapa Runnable-objekt och sedan skicka dem till den exekutor som kör dem.
Några av de bästa metoderna som ska följas när du använder Executor-ramverket är,
- Vi bör korsa och planera en kod för att granska topplistorna så att vi kan upptäcka dödläge såväl som livelock i koden.
- Java-kod ska alltid köras mot statiska analysverktyg. Exempel av statiska analysverktyg är FindBugs och PMD.
- Vi bör inte bara fånga undantag utan också felen i flertrådiga program.
Låt oss nu diskutera komponenterna i Executor Framework i Java.
Testamentsexekutor
Exekutören kan definieras som ett gränssnitt som används för att representera ett objekt som utför de uppgifter som ges till det. Huruvida uppgiften ska köras på aktuell eller ny tråd beror på den punkt från vilken anropet initierades vilket ytterligare beror på implementeringen.
Så med Executor kan vi koppla bort uppgifterna från den faktiska uppgiften och sedan köra dem asynkront.
Körningen av uppgiften med Executor behöver dock inte vara asynkron. Exekutörer kan också åberopa uppgiften direkt med hjälp av anropstråd.
Nedan följer ett exempel kod för att skapa Executor-instans:
public class Invoker implements Executor { @Override public void execute (Runnable r_interface) { r_interface.run(); } }
När invokern har skapats, som visas ovan, kan vi använda den för att utföra uppgiften enligt följande.
public void execute () { Executor executor = new Invoker (); executor.execute ( () -> { //perform task }); }
Observera att om uppgiften inte accepteras av exekutören, kastar den RejectedExecutionException.
ExecutorService
En ExecutorService (java.util.concurrent.ExecutorService) schemalägger de inlämnade uppgifterna enligt tillgängligheten för trådar och upprätthåller också en minneskö. ExecutorService fungerar som en komplett lösning för asynkron bearbetning av uppgifter.
För att använda ExecutorService i kod skapar vi en Runnable-klass. ExecutorService upprätthåller en trådpool och tilldelar även uppgifterna till trådarna. Uppgifter kan också stå i kö om tråden inte är tillgänglig.
Nedan följer ett enkelt exempel på 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(); } }
Produktion
I ovanstående program skapar vi en enkel ExecutorService-instans med en trådpool som består av 10 trådar. Det tilldelas sedan den körbara instansen och körs för att skriva ut ovanstående meddelande. Efter att meddelandet har skrivits ut stängs ExecutorService.
Trådpool
En trådpool i Java är en grupp arbetartrådar som kan återanvändas många gånger och tilldelas jobb.
En trådpool innehåller en grupp trådar med fast storlek. Varje tråd dras ut från trådpoolen och tilldelas en uppgift av tjänsteleverantören. När det tilldelade jobbet har slutförts ges tråden till trådpoolen igen.
Trådpool är fördelaktigt eftersom vi inte behöver skapa en ny tråd varje gång uppgiften är tillgänglig, vilket förbättrar prestandan. Den används i realtidsapplikationer som använder Servlet och JSP där trådpooler används för att behandla förfrågningar.
I applikationer med flera trådar sparar trådpoolen resurser och hjälper till att hålla parallellen inom fördefinierade gränser.
Nedanstående Java-program visar trådpoolen i Java.
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'); } }
Produktion
I programmen ovan finns det en trådpool med 5 trådar som skapas med 'newFixedThreadPool' -metoden. Sedan skapas trådarna och läggs till i poolen och tilldelas ExecutorService för körning.
Kan kallas i Java
Vi vet redan att vi kan skapa trådar med två metoder. Ett tillvägagångssätt är att utvidga Thread-klassen medan det andra tillvägagångssättet är att implementera ett körbart gränssnitt.
Trådar som skapats med Runnable-gränssnittet saknar dock en funktion, dvs. det returnerar inte ett resultat när tråden avslutas eller körs () slutför körningen. Det är här det anropbara gränssnittet kommer in i bilden.
vad är sdlc-faserna?
Med hjälp av ett kallbart gränssnitt definierar vi en uppgift så att den returnerar ett resultat. Det kan också kasta ett undantag. Det kallbara gränssnittet är en del av paketet java.util.concurrent.
Det anropbara gränssnittet ger en call () -metod som är på samma linjer som run () -metoden som tillhandahålls av det Runnable-gränssnittet, med den enda skillnaden att metoden call () returnerar ett värde och kastar kontrollerat undantag.
Metoden call () för Callable interface har följande prototyp.
public Object call () throws Exception;
Eftersom metoden call () returnerar ett objekt måste huvudtråden vara medveten om detta.
Därför bör returvärdet lagras i ett annat objekt som är känt för huvudtråden. Detta syfte betjänas genom att använda ett ”framtida” objekt. Ett framtida objekt är ett objekt som innehåller resultatet som returneras av en tråd. Eller med andra ord, det kommer att hålla resultatet när Callable återvänder.
Callable inkapslar en uppgift som ska köras på en annan tråd. Ett framtida objekt lagrar resultatet som returneras från en annan tråd.
Ett anropbart gränssnitt kan inte användas för att skapa en tråd. Vi behöver Runnable för att skapa en tråd. För att lagra resultatet krävs ett framtida objekt. Java tillhandahåller en konkret typ med namnet “FutureTask” som kombinerar funktionaliteten genom att implementera både Runnable och Future.
Vi skapar en FutureTask genom att förse en konstruktör med Callable. Detta FutureTask-objekt ges sedan till konstruktören i Thread-klassen för att skapa ett Thread-objekt.
Nedan följer ett Java-program som visar det kallbara gränssnittet och framtida objekt. Vi använder också FutureTask-objektet i detta program.
Som redan nämnts skapar vi i programmet en klass som implementerar ett Callable-gränssnitt med en åsidosatt call () -metod. I huvudmetoden skapar vi 10 FutureTask-objekt. Varje objektkonstruktör har ett kallbart klassobjekt som argument. Då associeras FutureTask-objektet med en trådinstans.
Därför skapar vi indirekt en tråd med ett gränssnittsobjekt som kan kallas.
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() + ' '); } } }
Produktion
Som visas i ovanstående program genererar call () -metoden för Callable som åsidosätts i klassen som implementerar Callable slumpmässiga nummer. När tråden har startats visar den dessa slumpmässiga siffror.
Vi använder också FutureTask-objekt i huvudfunktionen. Eftersom det implementerar Future-gränssnittet behöver vi inte lagra resultaten i trådobjekten. På samma sätt kan vi avbryta uppgiften, kontrollera om den är igång eller slutförd, och även få resultatet med FutureTask-objektet.
ReentrantLock i Java
Vi har diskuterat trådsynkronisering med det synkroniserade nyckelordet i detalj i vår senaste handledning. Användningen av det synkroniserade ordet för trådsynkronisering är den grundläggande metoden och är något styv.
Med hjälp av det synkroniserade nyckelordet kan en tråd endast låsa en gång. När en tråd går ut från det synkroniserade blocket tar nästa tråd också låset. Det finns ingen väntekö. Dessa problem kan orsaka svält av någon annan tråd eftersom det kanske inte kommer åt resurserna på länge.
För att lösa dessa problem behöver vi en flexibel metod för att synkronisera trådarna. ”Reentrant Locks” är den här metoden i Java som ger synkronisering med mycket större flexibilitet.
Klassen “ReentrantLock” implementerar Reentrant-lås och är en del av paketet “import java.util.concurrent.locks”. ReentrantLock-klassen ger metodsynkronisering för att komma åt delade resurser. Klasserna har också låsa och låsa upp metoder för att låsa / låsa upp resurser när de nås av trådar.
En speciell egenskap hos ReentrantLock är att tråden kan låsa den delade resursen mer än en gång med ReentrantLock. Det ger hållräkning som är inställt på en när tråden låser resursen.
Tråden kan komma in igen och komma åt resursen innan den låses upp. Varje gång tråden kommer åt resursen med hjälp av Reentrant-låset, ökas spärrräkningen med en. För varje upplåsning minskas hållantalet med en.
När spärrantalet når 0 låses den delade resursen upp.
ReentrantLock-klassen ger också en rättviseparameter som är ett booleskt värde som kan skickas med låskonstruktören. När rättvisa-parametern är satt till sant, så skickas låset till den längst väntande tråden när en tråd släpper låset. Detta förhindrar svält.
Reentrant-lås kan användas på följande sätt:
return_type method_name() { reentrantlock.lock(); try { //Do some work } catch(Exception e) { e.printStackTrace(); } finally { reentrantlock.unlock(); } }
Observera att upplåsningsuttalandet för ReentrantLock alltid är i slutblocket. Detta garanterar att låset släpps även om ett undantag kastas.
Låt oss implementera ett Java-program för att förstå 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(); } }
Produktion
I programmet ovan har vi skapat en tråd och använt ReentrantLock för den. Med hjälp av ReentrantLock kan du komma åt den delade resursen.
Semafor i Java
Nästa metod för trådsynkronisering är att använda Semaphore. Med hjälp av denna konstruktion som kallas semafor styrs åtkomst till en delad resurs via en räknare. Signaler skickas mellan trådarna så att vi kan skydda det kritiska avsnittet och också undvika missade signaler.
En semafor kan definieras som en variabel som används för att hantera samtidiga processer genom att synkronisera dessa processer. Semaforer används också för att synkronisera åtkomst till den delade resursen och därigenom undvika ett tävlingsvillkor. Tillståndet som ges till en tråd för åtkomst till den delade resursen av semafor kallas också för tillstånd.
Beroende på vilka funktioner de utför kan semaforer delas in i två typer:
# 1) Binär semafor: En binär semafor används för att synkronisera samtidiga processer och implementera ömsesidig uteslutning. En binär semafor antar endast två värden, dvs 0 och 1.
# 2) Räknar Semafor: Räkningssemaforen har ett värde som anger antalet processer som kan komma in i det kritiska avsnittet. När som helst anger värdet det maximala antalet processer som går in i det kritiska avsnittet.
Så hur fungerar en Semaphore?
Arbetet med en semafor kan sammanfattas i följande steg:
- Om semafor räknar> 0 betyder det att tråden har tillstånd att få åtkomst till kritisk sektion, och sedan minskas räkningen.
- Annars blockeras tråden tills tillståndet förvärvats.
- När tråden är klar med åtkomst till den delade resursen frigörs tillståndet och semaforantalet ökas så att en annan tråd kan upprepa ovanstående steg och få tillståndet.
Ovanstående steg för bearbetning av semaforer kan sammanfattas i nedanstående flödesschema.
I Java behöver vi inte implementera vår semafor men det ger en Semafor klass som implementerar semaforfunktionaliteten. Semaphore-klassen är en del av java.util.concurrent paket.
Semaphore-klassen ger följande konstruktörer med vilka vi kan skapa semaforobjekt:
Semaphore (int num_value) Semaphore (int num_value, boolean how)
Här,
bästa programmet för att fixa registerfel
num_value => initialvärde för tillståndsräkningen som bestämmer antalet trådar som kan komma åt den delade resursen.
hur => ställer in den ordning i vilken trådarna får tillstånd (hur = sant). Om hur = falskt följs ingen sådan ordning.
Nu kommer vi att implementera ett Java-program som visar Semaphore som används för att hantera den delade resursåtkomsten och förhindra loppstillståndet.
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. } }
Produktion
Detta program förklarade en klass för den delade resursen. Det förklarar också en trådklass där vi har en semaforvariabel som initialiseras i klasskonstruktören.
I den åsidosatta run () -metoden i Thread-klassen görs bearbetning av trådinstans där tråd förvärvar tillståndet, får åtkomst till en delad resurs och sedan frigör tillståndet.
I huvudmetoden förklarade vi två trådinstanser. Båda trådarna startas sedan och sedan väntar de med anslutningsmetoden. Slutligen visas räkningen, dvs. 0, vilket indikerar att båda trådarna har avslutats med den delade resursen.
Gaffel och gå med i Java
Fork / join-ramverket introducerades först i Java 7. Detta ramverk består av verktyg som kan påskynda parallell bearbetning. Den använder alla tillgängliga processorkärnor i systemet och slutför uppgiften. Fork / join-ramverket använder divide and conquer-metoden.
Grundidén bakom Fork / Join-ramverket är att det första ramverket 'Forks', dvs rekursivt bryter uppgiften i mindre enskilda deluppgifter tills uppgifterna är atomiska så att de kan utföras asynkront.
Efter att ha gjort detta 'går' uppgifterna samman, dvs. alla deluppgifter sammanfogas rekursivt till en enda uppgift eller returvärde.
Fork / join-ramverket har en pool av trådar som kallas 'ForkJoinPool'. Denna pool hanterar typen 'ForkJoinWorkerThread' av arbetartrådar, vilket ger effektiv parallell bearbetning.
ForkJoinPool hanterar arbetartrådarna och hjälper oss också att få information om trådpoolens prestanda och tillstånd. ForkJoinPool är en implementering av 'ExecutorService' som vi diskuterade ovan.
Till skillnad från arbetartrådar skapar ForkJoinPool inte en separat tråd för varje deluppgift. Varje tråd i ForkJoinPool bibehåller sin deque (dubbla kö) för att lagra uppgifter.
Dekken fungerar som trådens balans mellan arbetsbelastning och gör detta med hjälp av en 'arbetsstöldalgoritm' som beskrivs nedan.
Arbets stjälalgoritm
Vi kan definiera arbetsstöldalgoritmen i enkla ord som 'Om en tråd är fri,' stjäla 'arbetet från upptagen trådar'.
En arbetartråd kommer alltid att få uppgifterna från dess deque. När alla uppgifter i deken är uttömda och deque är tom, kommer arbetartråden att ta en uppgift från svansen på en annan deque eller från den 'globala postkön'.
På så sätt minimeras möjligheten att trådar tävlar om uppgifter och antalet gånger som tråden måste leta efter arbete minskas också. Detta beror på att tråden redan har fått den största delen av tillgängligt arbete och har avslutat den.
Så hur kan vi använda ForkJoinPool i ett program?
Den allmänna definitionen av ForkJoinPool är som följer:
public class ForkJoinPool extends AbstractExecutorService
Klassen ForkJoinPool är en del av paketet “java.util.concurrent”.
I Java 8 skapar vi en instans av ForkJoinPool med den statiska metoden 'common-pool ()' som ger en referens till den gemensamma poolen eller standardtrådspoolen.
ForkJoinPool commonPool = ForkJoinPool.commonPool ();
I Java 7 skapar vi en ForkJoinPool-instans och tilldelar den till fältet för verktygsklass som visas nedan.
public static ForkJoinPool forkJoinPool = new ForkJoinPool(2);
Ovanstående definition indikerar att poolen har en parallellitetsnivå på 2 så att poolen kommer att använda två processorkärnor.
För att komma åt ovanstående pool kan vi ge följande uttalande.
ForkJoinPool forkJoinPool = PoolUtil.forkJoinPool;
Bastypen för ForkJoinPool-uppgifter är “ForkJoinTask”. Vi bör utvidga en av dess underklasser, dvs. för ogiltiga uppgifter, RecursiveAction och för uppgifter som returnerar ett värde, RecursiveTask. Båda de utökade klasserna ger en abstrakt metodberäkning () där vi definierar uppgifternas logik.
Nedan följer ett exempel för att demonstrera 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()); } }
Produktion
I programmet ovan hittar vi antalet aktiva trådar i systemet före och efter att ha anropat metoden “anropa ()”. Metoden invoke () används för att skicka uppgifterna till poolen. Vi hittar också antalet tillgängliga processorkärnor i systemet.
Vanliga frågor
F # 1) Vad är Java Util Concurrent?
Svar: Paketet “java.util.concurrent” är en uppsättning klasser och gränssnitt som tillhandahålls av Java för att underlätta utvecklingen av samtidiga (flertrådade) applikationer. Med hjälp av detta paket kan vi direkt använda gränssnittet och klasserna samt API: er utan att behöva skriva våra klasser.
F # 2) Vilket av följande är samtidiga implementeringar som finns i java.util. samtidigt paket?
Svar: På hög nivå innehåller paketet java.util.concurrent verktyg som Executors, Synchronizers, Queues, Timings och Concurrent Collections.
F # 3) Vad är framtida Java?
Svar: Ett framtida objekt (java.util.concurrent.Future) används för att lagra resultatet som returneras av en tråd när det kallbara gränssnittet implementeras.
F # 4) Vad är trådsäkert i Java?
qa testintervjuer för erfarna
Svar: En trådsäker kod eller klass i Java är en kod eller klass som kan delas i en multitrådad eller samtidig miljö utan problem och ger förväntade resultat.
F # 5) Vad är den synkroniserade samlingen i Java?
Svar: En synkroniserad samling är en trådsäker samling. Metoden synkroniserad samling () av klassen java.util.Collections returnerar en synkroniserad (trådsäker) samling.
Slutsats
Med denna handledning har vi slutfört ämnet multitrådning och samtidighet i Java. Vi har diskuterat multithreading i detalj i våra tidigare tutorials. Här diskuterade vi samtidigheten och implementeringen relaterad till samtidighet och multithreading som ingår i paketet java.util.concurrent.
Vi diskuterade ytterligare två synkroniseringsmetoder, semaforer och ReentrantLock. Vi diskuterade också ForkJoinPool som används för att utföra uppgifterna genom att dela upp dem i enklare uppgifter och sedan slutligen gå med i resultatet.
Paketet java.util.concurrent stöder också Executor-ramverket och exekutörer som hjälper oss att köra trådar. Vi diskuterade också implementering av trådpool som består av återanvändbara trådar som returneras till poolen när körningen är klar.
Vi diskuterade ett annat gränssnitt som liknar Runnable som också hjälper oss att returnera ett resultat från tråden och det framtida objektet som används för att lagra det erhållna trådresultatet.
=> Se upp den enkla Java-träningsserien här.
Rekommenderad läsning
- Thread.Sleep () - Thread Sleep () Metod i Java med exempel
- Java-distribution: Skapande och utförande av Java JAR-fil
- Java Basics: Java Syntax, Java Class och Core Java Concepts
- Java Virtual Machine: Hur JVM hjälper till att köra Java-applikationen
- Åtkomstmodifierare i Java - Handledning med exempel
- Java Synchronized: Vad är trådsynkronisering i Java
- JAVA-handledning för nybörjare: 100+ praktiska Java-videohandledning
- Java-heltal och Java BigInteger-klass med exempel