Vodič za PriorityBlockingQueue u Javi

1. Uvod

U ovom ćemo se članku usredotočiti na PriorityBlockingQueue predavanja i prijeđite na nekoliko praktičnih primjera.

Polazeći od pretpostavke da već znamo što a Red je, prvo ćemo pokazati kako elementi u PriorityBlockingQueue poredani su po prioritetu.

Slijedom ovoga, pokazat ćemo kako se ova vrsta reda može koristiti za blokiranje niti.

Na kraju ćemo pokazati kako zajedničko korištenje ove dvije značajke može biti korisno pri obradi podataka u više niti.

2. Prioritet elemenata

Za razliku od standardnog reda, ne možete samo dodati bilo koju vrstu elementa u PriorityBlockingQueue. Dvije su mogućnosti:

  1. Dodavanje elemenata koji implementiraju Usporedive
  2. Dodavanje elemenata koji se ne provode Usporedive, pod uvjetom da navedete a Usporednik također

Korištenjem bilo kojeg Usporednik ili Usporedive implementacije za usporedbu elemenata, PriorityBlockingQueue uvijek će se sortirati.

Cilj je primijeniti logiku usporedbe na način na koji uvijek se prvo naručuje element s najvišim prioritetom. Zatim, kada uklonimo element iz svog reda, on će uvijek biti onaj s najvećim prioritetom.

Za početak, iskoristimo svoj red u jednoj niti, za razliku od upotrebe u više njih. Čineći to, olakšava dokazivanje kako su elementi poredani u jediničnom testu:

PriorityBlockingQueue red = novi PriorityBlockingQueue (); ArrayList polledElements = novi ArrayList (); queue.add (1); queue.add (5); red čekanja.doda (2); queue.add (3); queue.add (4); queue.drainTo (polledElements); assertThat (polledElements) .containEasectly (1, 2, 3, 4, 5);

Kao što vidimo, unatoč dodavanju elemenata u red slučajnim redoslijedom, oni će biti poredani kad ih počnemo anketirati. To je zato što Cijeli broj razredna oprema Usporedivo, koji će se pak koristiti za osiguravanje da ih izvodimo iz reda u rastućem redoslijedu.

To je također vrijedno napomenuti kada se uspoređuju dva elementa i ista su, nema jamstva kako će biti naručeni.

3. Korištenje Red blokirati

Da imamo posla sa standardnim redom, nazvali bismo anketa() za preuzimanje elemenata. Međutim, ako je red prazan, poziv na anketa() bi se vratio null.

The PriorityBlockingQueue provodi BlockingQueue sučelje, što nam daje neke dodatne metode koje nam to omogućavaju blok pri uklanjanju iz praznog reda. Pokušajmo koristiti uzeti() metoda, koja bi trebala učiniti upravo to:

PriorityBlockingQueue red = novi PriorityBlockingQueue (); nova nit (() -> {System.out.println ("Anketa ..."); isprobajte {Integer anketa = queue.take (); System.out.println ("Anketirano:" + anketa);} catch ( InterruptedException e) {e.printStackTrace ();}}). Start (); Thread.sleep (TimeUnit.SECONDS.toMillis (5)); System.out.println ("Dodavanje u red čekanja"); queue.add (1);

Iako se koristi spavati() je malo krhak način demonstriranja stvari, kad pokrenemo ovaj kôd vidjet ćemo:

Anketa ... Dodavanje u red Ispitano: 1 

To dokazuje uzeti() blokirano dok se ne doda stavka:

  1. Nit će ispisati "Anketa" kako bi dokazala da je započela
  2. Potom će se test zaustaviti oko pet sekundi, kako bi se dokazalo da je nit morala nazvati uzeti() do ovog trenutka
  3. Dodajemo u red i trebali bismo više-manje trenutno vidjeti "Anketirano: 1" da to dokažemo uzeti() vratio element čim postane dostupan

Također je vrijedno spomenuti da BlockingQueue sučelje nam također pruža načine blokiranja prilikom dodavanja u pune redove.

Međutim, a PriorityBlockingQueue je neograničen. To znači da nikada neće biti puna, pa će uvijek biti moguće dodavati nove elemente.

4. Zajedničko korištenje blokiranja i određivanja prioriteta

Sad kad smo objasnili dva ključna pojma a PriorityBlockingQueue, iskoristimo ih oboje zajedno. Jednostavno možemo proširiti naš prethodni primjer, ali ovaj put u red čekanja dodamo još elemenata:

Nit niti = nova nit (() -> {System.out.println ("Anketa ..."); while (true) {try {Integer anketa = queue.take (); System.out.println ("Anketa: "+ anketa);} catch (InterruptedException e) {e.printStackTrace ();}}}); nit.start (); Thread.sleep (TimeUnit.SECONDS.toMillis (5)); System.out.println ("Dodavanje u red čekanja"); queue.addAll (newArrayList (1, 5, 6, 1, 2, 6, 7)); Thread.sleep (TimeUnit.SECONDS.toMillis (1));

Opet, iako je ovo malo krhko zbog upotrebe spavati(), još uvijek nam pokazuje valjan slučaj upotrebe. Sada imamo red koji blokira, čekajući dodavanje elemenata. Zatim dodajemo puno elemenata odjednom, a zatim pokazujemo da će se njima rukovati u prioritetnom redoslijedu. Izlaz će izgledati ovako:

Anketa ... Dodavanje u red Anketirano: 1 Anketirano: 1 Anketirano: 2 Anketirano: 5 Anketirano: 6 Anketirano: 6 Anketirano: 7

5. Zaključak

U ovom smo priručniku pokazali kako možemo koristiti a PriorityBlockingQueue kako bismo blokirali nit dok joj se ne dodaju neke stavke, a također i da smo u mogućnosti obraditi te stavke na temelju njihovog prioriteta.

Implementacija ovih primjera može se naći na GitHubu. Ovo je projekt zasnovan na Mavenu, pa bi ga trebalo biti lako pokrenuti kakav jest.


$config[zx-auto] not found$config[zx-overlay] not found