Vejledning til PriorityBlockingQueue i Java

1. Introduktion

I denne artikel vil vi fokusere på PriorityBlockingQueue klasse og gå gennem nogle praktiske eksempler.

Startende med den antagelse, at vi allerede ved, hvad en er, vil vi først demonstrere hvordan elementer i PriorityBlockingQueue er ordnet efter prioritet.

Efter dette vil vi demonstrere, hvordan denne type kø kan bruges til at blokere en tråd.

Endelig viser vi, hvordan brug af disse to funktioner sammen kan være nyttigt, når vi behandler data på tværs af flere tråde.

2. Elementernes prioritet

I modsætning til en standardkø kan du ikke bare tilføje nogen form for element til en PriorityBlockingQueue. Der er to muligheder:

  1. Tilføjelse af elementer, der implementeres Sammenlignelig
  2. Tilføjelse af elementer, der ikke implementeres Sammenlignelig, forudsat at du giver en Komparator såvel

Ved at bruge enten Komparator eller den Sammenlignelig implementeringer for at sammenligne elementer, PriorityBlockingQueue vil altid blive sorteret.

Målet er at implementere sammenligningslogik på en måde, hvorpå elementet med højeste prioritet bestilles altid først. Derefter, når vi fjerner et element fra vores kø, vil det altid være det med den højeste prioritet.

Til at begynde med skal vi bruge vores kø i en enkelt tråd i modsætning til at bruge den på tværs af flere. Ved at gøre dette gør det det let at bevise, hvordan elementer bestilles i en enhedstest:

PriorityBlockingQueue kø = ny PriorityBlockingQueue (); ArrayList polledElements = ny ArrayList (); kø. tilføj (1); kø. tilføj (5); kø. tilføj (2); kø. tilføj (3); kø. tilføj (4); kø.drainTo (polledElements); assertThat (polledElements) .containsExactly (1, 2, 3, 4, 5);

Som vi kan se, til trods for at tilføje elementerne til køen i en tilfældig rækkefølge, vil de blive bestilt, når vi begynder at afstemme dem. Dette skyldes, at Heltal klasse redskaber Sammenlignelig, som igen vil blive brugt til at sikre, at vi tager dem ud af køen i stigende rækkefølge.

Det er også værd at bemærke det når to elementer sammenlignes og er ens, er der ingen garanti for, hvordan de bestilles.

3. Brug af at blokere

Hvis vi havde at gøre med en standardkø, ville vi ringe afstemning() for at hente elementer. Men hvis køen var tom, skal du ringe til afstemning() ville vende tilbage nul.

Det PriorityBlockingQueue implementerer BlockingQueue interface, som giver os nogle ekstra metoder, der giver os mulighed for det blokere ved fjernelse fra en tom kø. Lad os prøve at bruge tage() metode, som skulle gøre netop det:

PriorityBlockingQueue kø = ny PriorityBlockingQueue (); ny tråd (() -> {System.out.println ("Polling ..."); prøv {Integer poll = queue.take (); System.out.println ("Polled:" + poll);} catch ( InterruptedException e) {e.printStackTrace ();}}). Start (); Tråd.sove (TimeUnit.SECONDS.toMillis (5)); System.out.println ("Tilføjelse til kø"); kø. tilføj (1);

Selvom du bruger søvn() er en lidt skør måde at demonstrere ting på, når vi kører denne kode vil vi se:

Polling ... Tilføjelse til kø Pollet: 1 

Dette beviser det tage() blokeret, indtil et element blev tilføjet:

  1. Tråden udskriver "Polling" for at bevise, at den er startet
  2. Testen holder derefter pause i cirka fem sekunder for at bevise, at tråden skal have ringet tage() ved dette punkt
  3. Vi føjer til køen og skal mere eller mindre øjeblikkeligt se “Polled: 1” for at bevise det tage() returnerede et element, så snart det blev tilgængeligt

Det er også værd at nævne, at BlockingQueue interface giver os også måder at blokere, når vi tilføjer til fulde køer.

Imidlertid er en PriorityBlockingQueue er ubegrænset. Dette betyder, at det aldrig bliver fuldt, og det vil derfor altid være muligt at tilføje nye elementer.

4. Brug af blokering og prioritering sammen

Nu hvor vi har forklaret de to nøglebegreber i PriorityBlockingQueue, lad os bruge dem begge sammen. Vi kan simpelthen udvide vores tidligere eksempel, men denne gang tilføjer flere elementer til køen:

Trådtråd = ny tråd (() -> {System.out.println ("Polling ..."); mens (sand) {prøv {Integer poll = queue.take (); System.out.println ("Pollet: "+ afstemning);} fangst (InterruptedException e) {e.printStackTrace ();}}}); thread.start (); Thread.sleep (TimeUnit.SECONDS.toMillis (5)); System.out.println ("Tilføjelse til kø"); kø.addAll (newArrayList (1, 5, 6, 1, 2, 6, 7)); Thread.sleep (TimeUnit.SECONDS.toMillis (1));

Igen, mens dette er lidt skørt på grund af brugen af søvn(), det viser os stadig en gyldig brugssag. Vi har nu en kø, der blokerer og venter på, at elementer tilføjes. Vi tilføjer derefter mange elementer på én gang og viser derefter, at de håndteres i prioriteret rækkefølge. Outputtet ser sådan ud:

Polling ... Tilføjelse til kø Pollet: 1 Pollet: 1 Pollet: 2 Pollet: 5 Pollet: 6 Pollet: 6 Pollet: 7

5. Konklusion

I denne vejledning har vi demonstreret, hvordan vi kan bruge en PriorityBlockingQueue for at blokere en tråd, indtil der er tilføjet nogle emner til den, og også at vi er i stand til at behandle disse emner ud fra deres prioritet.

Implementeringen af ​​disse eksempler findes på GitHub. Dette er et Maven-baseret projekt, så det skal være let at køre som det er.