sql >> Database teknologi >  >> RDS >> Database

En introduktion til Concurrent Collection API'er i Java

De samtidige indsamlings-API'er, bortset fra Java Collection API, er et sæt samlings-API'er, der er designet og optimeret specifikt til synkroniseret multitrådadgang. De er grupperet under java.util.concurrent pakke. Denne artikel giver et overblik og introducerer dets brug ved at bruge et passende eksempelscenarie.

En oversigt

Java har understøttet multithreading og samtidighed fra starten. Trådene oprettes enten ved at implementere Runnable grænseflade eller udvidelse af tråden klasse. Synkroniseringen opnås af nøgleordet kaldet synkronisering . Java giver også mekanismen til kommunikation mellem trådene. Dette opnås ved hjælp af notify() og wait() metoder, som er en del af Objektet klasse. Selvom disse innovative multithreading-teknikker er en del af nogle af de fremragende funktioner i Java, kommer de noget til kort, når det gælder om at levere behovet for en programmør, som kræver intensiv multithreading-kapacitet ud af boksen. Dette skyldes, at et samtidig program har brug for mere end blot at kunne oprette tråde og lave nogle rudimentære manipulationer. Det kræver mange funktioner på højt niveau såsom trådpuljer, eksekveringsmanagere, semaforer og så videre.

Eksisterende samlingsramme

Java har allerede en komplet samlingsramme. Samlingerne er meget gode til, hvad de gør og kan også bruges i Java-trådsapplikationer. Der er også et nøgleord, kaldet synkroniseret , for at gøre dem trådsikre. Selvom det overfladisk kan virke rart at blive brugt i multithreading, er den måde, trådsikkerheden opnås på, den største flaskehals i dens samtidige implementering. Bortset fra eksplicit synkronisering er de ikke designet under paradigmet med samtidig implementering fra begyndelsen. Synkroniseringen af ​​disse samlinger opnås ved at serialisere al adgang til samlingens tilstand. Dette betyder, at selvom vi kan have en vis samtidighed, fungerer det på grund af underliggende serialiseret behandling efter et princip, som faktisk er det modsatte. Serialisering tærer hårdt på ydeevnen, især når flere tråde konkurrerer om den samlingsdækkende lås.

Nye samlings-API'er

Concurrent collection API'er er en tilføjelse til Java fra version 5 og er en del af pakken kaldet java.util.concurrent . De er en forbedring af eksisterende samlings-API'er og er designet til samtidig adgang fra flere tråde. For eksempel ConcurrentHashMap er faktisk den klasse, vi har brug for, når vi vil bruge et synkroniseret hash-baseret Kort implementering. På samme måde, hvis vi ønsker en gennemløbsdominant, trådsikker liste , kan vi faktisk bruge CopyOnWriterArrayList klasse. Det nye ConcurrentMap interface giver et antal sammensatte handlinger under en enkelt metode, såsom putIfPresent , computeIfPresent , erstat , flet , og så videre. Der er mange sådanne klasser, der er inden for den nye samtidige indsamlingsramme. For at nævne nogle få:ArrayBlockingQueue , ConcurrentLinkedDeque , ConcurrentLinkedQueue , ConcurrentSkipListMap , ConcurrentSkipListSet , CopyOnWriteArraySet , DelayQueue , LinkedBlockingDeque , LinkedBlockingQueue , LinkedTransferQueue , PriorityBlockingQueue , Synchronous Queue og andre.

Køer

Samlingstyperne, såsom og BlockingQueue , kan bruges til at holde et element midlertidigt, afventer hentning på en FIFO-måde til behandling. ConcurrentLinkQueue , på den anden side er en traditionel FIFO-kø implementeret som en ubegrænset, trådsikker kø baseret på sammenkædede noder. PriorityBlocking Queue er en ubegrænset blokeringskø, som bruger samme bestillingsnormer som den for ikke-samtidige PriorityQueue og forsyninger, der blokerer for hentning.

Kort

I ældre samlingsklasser, når synkronisering anvendes, holder den låse for varigheden af ​​hver operation. Der er operationer, såsom get metode til HashMap eller indeholder metode til Liste , som involverer indviklet beregning bag scenen, når den påberåbes. For at finde et bestemt element på en liste, kalder det automatisk lig med metode. Denne metode kræver en vis beregning for at sammenligne hvert element på listen; det kan tage lang tid at fuldføre opgaven. Dette er værre i en hash-baseret samling. Hvis elementerne i hash-kortene er ujævnt fordelt, kan det tage meget lang tid at krydse en lang liste og kalde lige. Dette er et problem, fordi det kan påvirke applikationens overordnede ydeevne.

I modsætning til HashMap , ConcurrentHashMap bruger en helt anden strategi. I stedet for at give en fælles lås for hver synkroniseret metode, bruger den en teknik kaldet lock stripping . Dette er en bedre løsning for både samtidighed og skalerbarhed. Låseafisolering bruger separate låse til separate spande. Som et resultat afkobles trådstridigheden fra den underliggende datastruktur og i stedet pålægges bøtten. For eksempel bruger implementeringen af ​​ConcurrentHashMap en række af 16 låse - som hver beskytter 1/16 af hash-bøtterne; spand N er beskyttet af lås N mod 16... dette reducerer behovet for enhver given lås med ca. en faktor 16. Det er på grund af denne teknik, at ConcurrentHashMap understøtter mindst 16 samtidige skribenter som standard, og flere kan rummes efter behov.

CopyOnWriterArrayList

Det er et fint alternativ til den synkroniserede Liste og kræver ikke, at du anvender en låsemekanisme under iteration. Iteratorerne beholder en reference til backing-arrayet ved starten af ​​iterationen og ændrer den ikke. Derfor kræver det en kort synkronisering at få indholdet af arrayet. Flere tråde kan få adgang til samlingen uden at forstyrre hinanden. Selv modifikation fra flere tråde lider ikke af uenighed. Der er et sæt modstykke til denne array-liste, kaldet CopyOnWriterSet , som kan bruges til at erstatte synkroniseret Set om samtidighedsbehov.

Et hurtigt eksempel

Der er mange klasser i den samtidige samling. Deres brug er ikke så svært for alle, der er bekendt med den ældre samlingsramme. For fuldstændighedens skyld er her et eksempel for at give et indblik i dets anvendelser i Java-programmering.

package org.mano.example;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class ProducerConsumerDemo {
   static BlockingQueue<Integer> queue = new
      LinkedBlockingQueue<>(5);
   public static void main(String[] args) throws
         InterruptedException {
      int noOfProducers = 7;
      int noOfConsumers = 9;
      for (inti = 0; i < noOfProducers; i++) {
         new Thread(new Producer(), "PRODUCER").start();
      }
      for (int i = 0; i < noOfConsumers; i++) {
         new Thread(new Consumer(), "CONSUMER").start();
      }
      System.exit(0);
   }
   static class Producer implements Runnable {
      Random random = new Random();
      public void run() {
         try {
            int num = random.nextInt(100);
            queue.put(num);
            System.out.println("Produced: " + num
               + " Queue size : "+ queue.size());
            Thread.sleep(100);
         } catch (InterruptedException ex) {
            System.out.println("Producer is interrupted.");
         }
      }
   }
   static class Consumer implements Runnable {
      public void run() {
         try {
            System.out.println("Consumed: " + queue.take()
               + " Queue size : "+ queue.size());
            Thread.sleep(100);
         } catch (InterruptedException ex) {
            System.out.println("Consumer is interrupted.");
         }
      }
   }
}

Konklusion

Den måske største fordel ved at bruge de samtidige indsamlingsklasser er deres skalerbarhed og lave risiko. De samtidige indsamlings-API'er i Java giver en række klasser, der er specifikt designet til at håndtere samtidige operationer. Disse klasser er alternativer til Java Collection Framework og giver lignende funktionalitet undtagen med yderligere understøttelse af samtidighed. Derfor er læringskurven for programmøren, der allerede kender til Java Collection Framework, næsten flad. Klasserne er defineret i pakken java.util.concurrent . Her har jeg forsøgt at give et overblik for at komme i gang og bruge samlings-API'erne, hvor det er nødvendigt.

Referencer

  • Java API-dokumentation
  • Goetz, Brian og Tim Peierls. Java samtidighed i praksis . Pearson, 2013.

  1. Simulering af MySQL's ORDER BY FIELD() i Postgresql

  2. Multi-Cloud Full Database Cluster Failover indstillinger for PostgreSQL

  3. Hvorfor ugyldig konvertering anmodet om FEJLKODE:17132?

  4. Sådan finder du maksimale værdier i rækker