concurrency java semaphore
En aquest tutorial es parlarà de components del paquet java.util.concurrent com ara Java Semaphore, Executor Framework, ExecutorService per implementar la simultaneïtat a Java:
Dels nostres tutorials anteriors sobre Java, sabem que la plataforma Java admet programació simultània des de zero. La unitat bàsica de simultaneïtat és un fil i hem discutit detalladament els fils i el multitreading a Java.
A partir de Java 5, es va afegir a la plataforma Java un paquet anomenat ‘java.util.concurrent’. Aquest paquet conté un conjunt de classes i biblioteques que faciliten al programador el desenvolupament d'aplicacions simultànies (multi-threaded). Amb aquest paquet, no hem d’escriure classes complexes, ja que tenim implementacions preparades per a la majoria dels conceptes concurrents.
=> Consulteu TOTS els tutorials de Java aquí.
Referència indefinida a la funció de c ++
En aquest tutorial, analitzarem els diversos components del paquet java.util.concurrent pel que fa a la simultaneïtat i el multithreading a Java.
Què aprendreu:
java.util.concurrent Package
A continuació es detallen els diferents components del paquet java.util.concurrent pel que fa a la simultaneïtat i el multithreading a Java. Explorem cada component en detall amb l'ajut d'exemples senzills de programació. Alguns dels components que farem
discutir són:
- Marc executor
- ExecutorService
- ThreadPool
- Cridable
- Panys- ReentrantLock
- Semàfor
- ForkJoinPool
Executor Framework a Java
Executor Framework a Java es va llançar amb la versió JDK 5. El marc executor (java.util.concurrent.Executor) és un marc que consisteix en components que ens ajuden a gestionar de manera eficient diversos fils.
Mitjançant l'Executor Framework, podem executar objectes que es poden executar reutilitzant els fils ja existents. No hem de crear fils nous cada vegada que necessitem executar objectes.
L'API Executor separa o desvincula l'execució d'una tasca de la tasca real mitjançant un Marmessor . Un executor està centrat en la interfície Executor i té subinterfícies, és a dir, ExecutorService i la classe ThreadPoolExecutor.
Així, utilitzant Executor, només hem de crear objectes Runnable i enviar-los a l'executor que els executa.
Algunes de les millors pràctiques que cal seguir mentre s’utilitza el marc Executor són:
- Hauríem de comprovar i planificar un codi per revisar les llistes principals, de manera que puguem detectar el bloqueig i el blocatge en temps real al codi.
- El codi Java sempre s’ha d’executar contra eines d’anàlisi estàtica. Exemples d’eines d’anàlisi estàtica són FindBugs i PMD.
- No només hauríem de detectar excepcions, sinó també els errors dels programes de diversos fils.
Ara analitzem els components d'Executor Framework a Java.
Marmessor
L'executor es pot definir com una interfície que s'utilitza per representar un objecte que executa les tasques que se li proporcionen. Si la tasca s'ha d'executar en el fil actual o nou depèn del punt des d'on es va iniciar la invocació, que depèn encara més de la implementació.
Per tant, amb Executor podem separar les tasques de la tasca real i executar-les de manera asíncrona.
No obstant això, l'execució de la tasca mitjançant Executor no ha de ser asíncrona. Els executors també poden invocar la tasca instantàniament mitjançant el fil d'invocació.
A continuació es mostra un exemple de codi per crear una instància Executor:
public class Invoker implements Executor { @Override public void execute (Runnable r_interface) { r_interface.run(); } }
Un cop creat l'invocador, tal com es mostra més amunt, el podem utilitzar per executar la tasca de la següent manera.
public void execute () { Executor executor = new Invoker (); executor.execute ( () -> { //perform task }); }
Tingueu en compte que si l'executor no accepta la tasca, llança RejectedExecutionException.
ExecutorService
Un ExecutorService (java.util.concurrent.ExecutorService) programa les tasques enviades segons la disponibilitat de fils i també manté una cua de memòria. ExecutorService actua com una solució completa per al processament asíncron de tasques.
Per utilitzar ExecutorService al codi, creem una classe Runnable. ExecutorService manté una agrupació de fils i també assigna les tasques als fils. Les tasques també es poden fer cua en cas que el fil no estigui disponible.
A continuació es mostra un exemple senzill d'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(); } }
Sortida
Al programa anterior, creem una simple instància ExecutorService amb un grup de fils que consta de 10 fils. Després s’assigna a la instància Runnable i s’executa per imprimir el missatge anterior. Després d'imprimir el missatge, es tanca ExecutorService.
Grup de fils
Un grup de fils a Java és un grup de fils de treball que es poden reutilitzar moltes vegades i assignar feines.
Un grup de fils conté un grup de fils de mida fixa. Cada fil es treu del grup de fils i el proveïdor de serveis assigna una tasca. Un cop finalitzada la tasca assignada, el fil es torna a donar a l'agrupació de fils.
El grup de fils és avantatjós ja que no hem de crear un fil nou cada vegada que la tasca està disponible, de manera que es millora el rendiment. S’utilitza en aplicacions en temps real que utilitzen Servlet i JSP on s’utilitzen agrupacions de fils per processar les sol·licituds.
En aplicacions de diversos fils, el grup de fils estalvia recursos i ajuda a contenir el paral·lelisme dins de límits predefinits.
El programa Java següent mostra el grup de fils a 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'); } }
Sortida
Als programes anteriors, hi ha un grup de fils de 5 fils que es creen mitjançant el mètode 'newFixedThreadPool'. A continuació, els fils es creen i s'afegeixen a l'agrupació i s'assignen a l'ExecutorService per a l'execució.
Cridable a Java
Ja sabem que podem crear fils mitjançant dos enfocaments. Un enfocament és ampliar la classe Thread mentre que el segon és implementar una interfície Runnable.
Tanmateix, els fils creats amb la interfície Runnable no tenen una característica, és a dir, no retorna cap resultat quan el fil s’acaba o s’executa () completa l’execució. Aquí és on apareix la interfície Callable.
Mitjançant una interfície Callable definim una tasca perquè torni un resultat. També pot generar una excepció. La interfície trucable forma part del paquet java.util.concurrent.
La interfície Callable proporciona un mètode call () que es troba en les línies similars al mètode run () proporcionat per la interfície Runnable amb l'única diferència que el mètode call () retorna un valor i genera una excepció marcada.
El mètode call () de la interfície Callable té el següent prototip.
public Object call () throws Exception;
Com que el mètode call () retorna un objecte, el fil principal n'ha de ser conscient.
Per tant, el valor de retorn s’ha d’emmagatzemar en un altre objecte conegut pel fil principal. Aquest propòsit es fa servir mitjançant un objecte 'Futur'. Un objecte Futur és un objecte que conté el resultat retornat per un fil. O, dit d’una altra manera, mantindrà el resultat quan tornarà Callable.
preguntes i respostes d’entrevistes de suport tècnic pdf
Callable encapsula una tasca que s'hauria d'executar en un altre fil. Un objecte Future emmagatzema el resultat retornat d’un altre fil.
No es pot utilitzar una interfície trucable per crear un fil. Necessitem Runnable per crear un fil. Després, per emmagatzemar el resultat, cal un objecte Future. Java proporciona un tipus concret anomenat 'FutureTask' que combina la funcionalitat implementant Runnable i Future.
Creem una FutureTask proporcionant Callable a un constructor. Aquest objecte FutureTask es lliura al constructor de la classe Thread per crear un objecte Thread.
A continuació es mostra un programa Java que demostra la interfície Callable i l’objecte Future. També utilitzem l'objecte FutureTask en aquest programa.
Com ja s'ha esmentat, al programa creem una classe que implementa una interfície cridable amb un mètode call () anul·lat. En el mètode principal, creem 10 objectes FutureTask. Cada constructor d'objectes té com a argument un objecte de classe Callable. A continuació, l'objecte FutureTask s'associa a una instància de fil.
Per tant, indirectament creem un fil mitjançant un objecte d'interfície cridable.
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() + ' '); } } }
Sortida
Com es mostra al programa anterior, el mètode call () de Callable, que es substitueix a la classe que implementa Callable, genera números aleatoris. Un cop iniciat el fil, mostra aquests números aleatoris.
A més, fem servir objectes FutureTask a la funció principal. A mesura que implementa la interfície Future, no necessitem emmagatzemar els resultats als objectes Thread. De la mateixa manera, podem cancel·lar la tasca, comprovar si s’està executant o completar i també obtenir el resultat mitjançant l’objecte FutureTask.
ReentrantLock a Java
En el nostre últim tutorial, hem parlat detalladament de la sincronització de fils mitjançant la paraula clau sincronitzada. L’ús de la paraula sincronitzada per a la sincronització de fils és el mètode bàsic i és una mica rígid.
Amb la paraula clau sincronitzada, un fil només es pot bloquejar una vegada. A més, després que un fil surt del bloc sincronitzat, el fil següent agafa el bloqueig. No hi ha cua d’espera. Aquests problemes poden provocar la inanició d'algun altre fil conductor, ja que pot ser que no pugui accedir als recursos durant molt de temps.
Per solucionar aquests problemes, necessitem un mètode flexible de sincronització dels fils. El 'Panys reentrants' és aquest mètode de Java que proporciona sincronització amb molta més flexibilitat.
La classe 'ReentrantLock' implementa bloquejos Reentrant i forma part del paquet 'import java.util.concurrent.locks'. La classe ReentrantLock proporciona el mètode de sincronització per accedir a recursos compartits. Les classes també tenen mètodes de bloqueig i desbloqueig per bloquejar / desbloquejar recursos quan s’accedeixen a través de fils.
Una característica peculiar de ReentrantLock és que el fil pot bloquejar el recurs compartit més d’una vegada mitjançant ReentrantLock. Proporciona un recompte de retenció que s'estableix en un quan el fil bloqueja el recurs.
El fil pot tornar a entrar i accedir al recurs abans de desbloquejar-lo. Cada vegada que el fil accedeix al recurs mitjançant el bloqueig Reentrant, el recompte de retenció s'incrementa en un. Per a cada desbloqueig, el recompte de retenció es redueix en un.
Quan el recompte de retenció arriba a 0, el recurs compartit es desbloqueja.
La classe ReentrantLock també proporciona un paràmetre d’equitat que és un valor booleà que es pot passar amb el constructor del bloqueig. Quan el paràmetre d’equitat s’estableix en true, cada vegada que un fil allibera el bloqueig, el bloqueig es passa al fil d’espera més llarg. Això evita la fam.
Els panys Reentrant es poden utilitzar de la següent manera:
return_type method_name() { reentrantlock.lock(); try { //Do some work } catch(Exception e) { e.printStackTrace(); } finally { reentrantlock.unlock(); } }
Tingueu en compte que la declaració de desbloqueig de ReentrantLock sempre es troba al bloc final. Això garanteix que el pany s’alliberi fins i tot si es produeix una excepció.
Implantem un programa Java per entendre 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(); } }
Sortida
Al programa anterior, hem creat un fil i hem utilitzat ReentrantLock per a això. Mitjançant ReentrantLock es pot accedir al recurs compartit.
Semàfor a Java
El següent mètode de sincronització de fils és utilitzar Semaphore. Mitjançant aquesta construcció anomenada semàfor, l’accés a un recurs compartit es controla a través d’un comptador. Els senyals s’envien entre els fils perquè puguem protegir la secció crítica i evitar també els senyals perduts.
Un semàfor es pot definir com una variable que s’utilitza per gestionar processos simultanis sincronitzant aquests processos. Els semàfors també s’utilitzen per sincronitzar l’accés al recurs compartit i evitar així una condició de carrera. El permís donat a un fil per accedir al recurs compartit per semàfor també s’anomena permís.
Segons les funcions que facin, els semàfors es poden dividir en dos tipus:
# 1) Semàfor binari: S'utilitza un semàfor binari per sincronitzar processos concurrents i implementar exclusió mútua. Un semàfor binari assumeix només dos valors, és a dir, 0 i 1.
# 2) Comptar semàfor: El semàfor de recompte té un valor que indica el nombre de processos que poden entrar a la secció crítica. En qualsevol moment, el valor indica el nombre màxim de processos que entren a la secció crítica.
Llavors, com funciona un semàfor?
El funcionament d'un semàfor es pot resumir en els passos següents:
- Si el recompte de semàfors> 0 vol dir que el fil té permís per accedir a la secció crítica i que el recompte es decrementa.
- En cas contrari, el fil es bloqueja fins que s’adquireix el permís.
- Quan s'acaba el fil amb l'accés al recurs compartit, s'allibera el permís i s'incrementa el recompte de semàfors perquè un altre fil pugui repetir els passos anteriors i adquirir el permís.
Els passos anteriors per al treball dels semàfors es poden resumir al diagrama de flux següent.
A Java, no necessitem implementar el nostre semàfor, però proporciona un Semàfor classe que implementa la funcionalitat del semàfor. La classe Semaphore forma part del java.util.concurrent paquet.
La classe Semaphore proporciona els següents constructors mitjançant els quals podem crear objectes semaphore:
Semaphore (int num_value) Semaphore (int num_value, boolean how)
Aquí,
número_valor => valor inicial del recompte de permisos que determina el nombre de fils que poden accedir al recurs compartit.
com => defineix l'ordre en què es concediran els fils als permisos (com = cert). Si com = fals, no se segueix aquest ordre.
Ara implementarem un programa Java que demostrarà el semàfor que s’utilitza per gestionar l’accés de recursos compartits i evitar la condició de la cursa.
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. } }
Sortida
Aquest programa va declarar una classe per al recurs compartit. També declara una classe de fil en què tenim una variable de semafor que s’inicialitza al constructor de classes.
En el mètode overridden run () de la classe Thread, es fa el processament de la instància de thread en què el thread adquireix el permís, accedeix a un recurs compartit i després allibera el permís.
Al mètode principal, hem declarat dues instàncies de fil. Els dos fils s'inicien i esperen amb el mètode d'unió. Finalment, es mostra el recompte, és a dir, 0 que indica que els dos fils han acabat amb el recurs compartit.
Forquilla i unió a Java
El framework fork / join es va introduir per primera vegada a Java 7. Aquest framework consisteix en eines que poden accelerar el processament en paral·lel. Utilitza tots els nuclis de processador disponibles al sistema i completa la tasca. El framework fork / join utilitza l’enfocament divideix i conquesta.
La idea bàsica darrere del marc Fork / Join és que el primer marc 'Forks', és a dir, divideix recursivament la tasca en subtasques individuals més petites fins que les tasques siguin atòmiques perquè es puguin executar de manera asíncrona.
Després de fer-ho, les tasques s'uneixen, és a dir, totes les subtasques s'uneixen recursivament en una sola tasca o retornen el valor.
El framework fork / join té un conjunt de fils coneguts com a 'ForkJoinPool'. Aquest grup gestiona el tipus de fils de treball 'ForkJoinWorkerThread', proporcionant així un processament paral·lel eficaç.
ForkJoinPool gestiona els fils de treball i també ens ajuda a obtenir informació sobre el rendiment i l'estat de l'agrupació de fils. El ForkJoinPool és una implementació del 'ExecutorService' que hem comentat anteriorment.
A diferència dels fils de treball, el ForkJoinPool no crea un fil separat per a cada subtasca. Cada fil del ForkJoinPool manté el seu deque (cua de doble extrem) per emmagatzemar tasques.
El deque actua com a equilibri de càrrega de treball del fil i ho fa amb l'ajut d'un 'algorisme de robatori de treball' que es descriu a continuació.
Algorisme de robatori de treballs
Podem definir l'algorisme de robatori de treball en paraules simples com 'Si un fil està lliure,' roba 'la feina dels fils ocupats'.
Un fil de treballador sempre obtindrà les tasques del seu deque. Quan s’esgotin totes les tasques del deque i el deque estigui buit, el fil del treballador prendrà una tasca de la cua d’un altre deque o de la ‘cua d’entrada global’.
D'aquesta manera, es minimitza la possibilitat que els fils competeixin per tasques i també es redueix el nombre de vegades que el fil ha de cercar feina. Això es deu al fet que el fil ja té la part més gran de treball disponible i l’ha acabat.
Llavors, com podem utilitzar el ForkJoinPool en un programa?
La definició general de ForkJoinPool és la següent:
public class ForkJoinPool extends AbstractExecutorService
La classe ForkJoinPool forma part del paquet 'java.util.concurrent'.
A Java 8, creem una instància del ForkJoinPool mitjançant el seu mètode estàtic 'common-pool ()' que proporciona una referència a l'agrupació comuna o a l'agrupació de fils predeterminada.
ForkJoinPool commonPool = ForkJoinPool.commonPool ();
A Java 7, creem una instància ForkJoinPool i l’assignem al camp de la classe d’utilitat com es mostra a continuació.
public static ForkJoinPool forkJoinPool = new ForkJoinPool(2);
La definició anterior indica que el grup té un nivell de paral·lelisme de 2, de manera que el grup farà servir 2 nuclis de processador.
Per accedir a l'agrupació anterior, podem donar la següent afirmació.
ForkJoinPool forkJoinPool = PoolUtil.forkJoinPool;
El tipus base per a tasques de ForkJoinPool és 'ForkJoinTask'. Hauríem d’estendre una de les seves subclasses, és a dir, per a tasques nul·les, la RecursiveAction i per a les tasques que retornen un valor, la RecursiveTask. Les dues classes ampliades proporcionen un mètode abstracte compute () en el qual definim la lògica de la tasca.
A continuació es mostra un exemple per demostrar el 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()); } }
Sortida
Al programa anterior, trobem el nombre de fils actius al sistema abans i després de cridar al mètode 'invoke ()'. El mètode invoke () s'utilitza per enviar les tasques a l'agrupació. També trobem el nombre de nuclis de processador disponibles al sistema.
Preguntes freqüents
P # 1) Què és Java Util Concurrent?
Resposta: El paquet 'java.util.concurrent' és un conjunt de classes i interfícies proporcionades per Java per facilitar el desenvolupament d'aplicacions simultànies (multi-threaded). Mitjançant aquest paquet podem utilitzar directament la interfície i les classes, així com les API, sense haver d’escriure les nostres classes.
Q # 2) Quins dels següents són implementacions simultànies presents a java.util. paquet simultani?
Resposta: A un nivell alt, el paquet java.util.concurrent conté utilitats com ara executors, sincronitzadors, cues, temporitzacions i col·leccions simultànies.
P # 3) Què és Future Java?
Resposta: Un objecte Future (java.util.concurrent.Future) s’utilitza per emmagatzemar el resultat retornat per un fil quan s’implementa la interfície cridable.
Q # 4) Què és el thread-safe a Java?
Resposta: Un codi o classe segura de fils a Java és un codi o una classe que es pot compartir en un entorn multi-thread o simultani sense problemes i produeix els resultats esperats.
P # 5) Què és la col·lecció sincronitzada a Java?
Resposta: Una col·lecció sincronitzada és una col·lecció segura per a fils. El mètode synchronized collection () de la classe java.util.Collections retorna una col·lecció sincronitzada (thread-safe).
Conclusió
Amb aquest tutorial, hem completat el tema del multi-threading i la simultaneïtat a Java. Hem parlat detalladament del multithreading en els nostres tutorials anteriors. Aquí, hem discutit la simultaneïtat i la implementació relacionades amb la simultaneïtat i el multithreading que formen part del paquet java.util.concurrent.
Vam discutir dos mètodes de sincronització més, els semàfors i ReentrantLock. També vam discutir el ForkJoinPool que s’utilitza per executar les tasques dividint-les en tasques més senzilles i, finalment, unint-les al resultat.
per què la meva passarel·la predeterminada continua sense connexió
El paquet java.util.concurrent també admet el marc Executor i els executors que ens ajuden a executar fils. També vam parlar de la implementació de l'agrupació de fils que consisteix en fils reutilitzables que es retornen a l'agrupació quan s'acaba l'execució.
Vam discutir una altra interfície similar a Runnable que també ens ajuda a retornar un resultat del fil i de l'objecte Future utilitzat per emmagatzemar el resultat del fil obtingut.
=> Vigileu aquí les sèries de formació Java senzilles.
Lectura recomanada
- Thread.Sleep (): mètode Thread Sleep () a Java amb exemples
- Desplegament de Java: creació i execució del fitxer JAR de Java
- Conceptes bàsics de Java: sintaxi de Java, Java Class i conceptes bàsics de Java
- Màquina virtual Java: com ajuda JVM a executar aplicacions Java
- Modificadors d'accés a Java: tutorial amb exemples
- Java sincronitzat: què és la sincronització de fils a Java
- Tutorial JAVA per a principiants: més de 100 tutorials pràctics de vídeo Java
- Java Integer i Java BigInteger Class amb exemples