Panduan PriorityBlockingQueue di Java

1. Pengenalan

Dalam artikel ini, kita akan memfokus pada kelas PriorityBlockingQueue dan membahas beberapa contoh praktikal.

Bermula dengan anggapan bahawa kita sudah tahu apa itu Antrian , kita akan pertama kali menunjukkan bagaimana elemen dalam PriorityBlockingQueue disusun mengikut keutamaan .

Setelah ini, kami akan menunjukkan bagaimana antrian jenis ini dapat digunakan untuk menyekat utas.

Akhirnya, kami akan menunjukkan bagaimana penggunaan kedua-dua ciri ini dapat berguna ketika memproses data merentasi beberapa utas.

2. Keutamaan Elemen

Tidak seperti barisan standard, anda tidak boleh menambahkan jenis elemen apa pun ke PriorityBlockingQueue. Terdapat dua pilihan:

  1. Menambah elemen yang melaksanakan Sebanding
  2. Menambah elemen yang tidak melaksanakan Comparable , dengan syarat anda menyediakan Comparator juga

Dengan menggunakan implementasi Comparator atau Comparable untuk membandingkan elemen, PriorityBlockingQueue akan sentiasa disusun.

Tujuannya adalah untuk menerapkan logik perbandingan dengan cara elemen keutamaan tertinggi selalu disusun terlebih dahulu . Kemudian, apabila kita membuang elemen dari barisan kita, elemen tersebut akan sentiasa menjadi keutamaan.

Sebagai permulaan, mari kita gunakan barisan kami dalam satu utas, dan bukannya menggunakannya di beberapa rangkaian. Dengan melakukan ini, memudahkan untuk membuktikan bagaimana elemen disusun dalam ujian unit:

PriorityBlockingQueue queue = new PriorityBlockingQueue(); ArrayList polledElements = new ArrayList(); queue.add(1); queue.add(5); queue.add(2); queue.add(3); queue.add(4); queue.drainTo(polledElements); assertThat(polledElements).containsExactly(1, 2, 3, 4, 5);

Seperti yang kita lihat, walaupun menambahkan elemen ke dalam barisan dalam urutan rawak, elemen tersebut akan disusun ketika kita mulai mengundinya. Ini kerana kelas Integer menerapkan Comparable, yang pada gilirannya akan digunakan untuk memastikan kita mengeluarkannya dari barisan dalam urutan menaik.

Perlu diperhatikan bahawa apabila dua elemen dibandingkan dan sama, tidak ada jaminan bagaimana ia akan disusun.

3. Menggunakan Queue to Block

Sekiranya kita berhadapan dengan barisan standard, kita akan memanggil poll () untuk mengambil elemen. Walau bagaimanapun, jika barisan kosong, panggilan untuk mengundi () akan menjadi sifar.

The PriorityBlockingQueue alat yang BlockingQueue antara muka, yang memberikan kita beberapa kaedah tambahan yang membolehkan kita untuk menyekat ketika mengeluarkan dari barisan yang kosong . Mari cuba gunakan kaedah take () , yang seharusnya betul:

PriorityBlockingQueue queue = new PriorityBlockingQueue(); new Thread(() -> { System.out.println("Polling..."); try { Integer poll = queue.take(); System.out.println("Polled: " + poll); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); Thread.sleep(TimeUnit.SECONDS.toMillis(5)); System.out.println("Adding to queue"); queue.add(1);

Walaupun menggunakan sleep () adalah cara yang agak rapuh untuk menunjukkan sesuatu, ketika kita menjalankan kod ini kita akan melihat:

Polling... Adding to queue Polled: 1 

Ini membuktikan bahawa take () disekat sehingga item ditambahkan:

  1. Benang akan mencetak "Polling" untuk membuktikan bahawa ia dimulakan
  2. Ujian kemudian akan berhenti selama sekitar lima saat, untuk membuktikan bahawa utas mesti disebut take () pada tahap ini
  3. Kami menambah barisan, dan lebih kurang akan melihat "Polled: 1" seketika untuk membuktikan bahawa take () mengembalikan elemen sebaik sahaja ia tersedia

Perlu juga disebutkan bahawa antara muka BlockingQueue juga memberi kita cara untuk menyekat ketika menambah barisan penuh.

Walau bagaimanapun, PriorityBlockingQueue tidak terhad. Ini bermaksud bahawa ia tidak akan pernah penuh, oleh itu selalu dapat menambahkan elemen baru.

4. Menggunakan Penyekatan dan Keutamaan Bersama

Sekarang setelah kami menerangkan dua konsep utama PriorityBlockingQueue, mari kita gunakan keduanya bersama-sama. Kita boleh memperluas contoh sebelumnya, tetapi kali ini menambah lebih banyak elemen ke dalam barisan:

Thread thread = new Thread(() -> { System.out.println("Polling..."); while (true) { try { Integer poll = queue.take(); System.out.println("Polled: " + poll); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); Thread.sleep(TimeUnit.SECONDS.toMillis(5)); System.out.println("Adding to queue"); queue.addAll(newArrayList(1, 5, 6, 1, 2, 6, 7)); Thread.sleep(TimeUnit.SECONDS.toMillis(1));

Sekali lagi, walaupun ini agak rapuh kerana penggunaan tidur (), ia masih menunjukkan kes penggunaan yang sah. Kami kini mempunyai barisan yang menyekat, menunggu elemen ditambahkan. Kami kemudian menambah banyak elemen sekaligus, dan kemudian menunjukkan bahawa elemen tersebut akan dikendalikan mengikut urutan keutamaan. Keluarannya akan kelihatan seperti ini:

Polling... Adding to queue Polled: 1 Polled: 1 Polled: 2 Polled: 5 Polled: 6 Polled: 6 Polled: 7

5. Kesimpulan

Dalam panduan ini, kami telah menunjukkan bagaimana kami dapat menggunakan PriorityBlockingQueue untuk menyekat utas sehingga beberapa item telah ditambahkan ke dalamnya, dan juga bahawa kami dapat memproses item tersebut berdasarkan keutamaannya.

Pelaksanaan contoh-contoh ini boleh didapati di GitHub. Ini adalah projek berasaskan Maven, jadi semestinya mudah dijalankan sebagaimana adanya.