Artikel ini terutama berbicara tentang koleksi yang terlibat dalam konkurensi. Untuk koleksi biasa, silakan merujuk ke [Tinjauan Koleksi Java]
1. Apa itu Blockingqueue
BlockingQueue adalah antrian blocking. Dari kata pemblokiran, dapat dilihat bahwa akses ke antrian pemblokiran dapat menyebabkan penyumbatan dalam beberapa kasus. Ada dua kasus yang diblokir utama:
1. Saat antrian penuh, itu akan diaktifkan.
2. Saat antrian kosong, itu akan keluar dari antrian.
Oleh karena itu, ketika utas mencoba mengantri antrian yang sudah penuh, itu akan diblokir kecuali utas lain melakukan operasi antrian; Demikian pula, ketika sebuah utas mencoba mengantri antrian kosong, itu akan diblokir kecuali utas lain memiliki operasi antrian.
Di Java, antarmuka BlockingQueue terletak di paket java.util.concurrent (disediakan dalam versi Java 5). Dari karakteristik antrian pemblokiran yang diperkenalkan di atas, dapat dilihat bahwa antrian pemblokiran-aman-aman.
2. Cara menggunakan blockingqueue
Antrian pemblokiran terutama digunakan dalam skenario produsen/konsumen. Gambar berikut menunjukkan produksi utas dan skenario konsumsi utas:
Utas yang bertanggung jawab untuk produksi terus -menerus membuat objek baru dan memasukkannya ke dalam antrian pemblokiran sampai batas atas antrian ini tercapai. Setelah antrian mencapai batas atasnya, utas produksi akan diblokir sampai benang yang dikonsumsi mengkonsumsi antrian. Demikian pula, utas yang bertanggung jawab untuk konsumsi terus -menerus mengkonsumsi objek dari antrian sampai antrian kosong. Ketika antrian kosong, utas konsumsi akan diblokir kecuali jika objek baru dalam antrian dimasukkan.
3. Metode dalam Antarmuka Blockingqueue
Ada empat set metode untuk memblokir antrian untuk melakukan insert , remove dan examine masing -masing. Ketika operasi yang sesuai dengan setiap set metode tidak dapat dieksekusi segera, akan ada reaksi yang berbeda. Tabel berikut mencantumkan metode ini dengan cara yang diklasifikasikan:
| - | Melempar pengecualian | Nilai khusus | Blok | Kali keluar |
|---|---|---|---|---|
| Menyisipkan | tambahkan (o) | menawarkan (o) | put (o) | Penawaran (O, Timeout, TimeUnit) |
| Menghapus | hapus (o) | pemilihan() | mengambil() | jajak pendapat (timeout, timeunit) |
| Meneliti | elemen() | mengintip() |
Karakteristik yang sesuai dari empat set metode ini adalah:
1. Throwsexception: Jika operasi tidak dapat dilakukan segera, pengecualian akan dilemparkan.
2. ValueValue: Jika operasi tidak dapat dilakukan segera, nilai khusus akan dikembalikan, biasanya benar atau salah
3. Blok: Jika operasi tidak dapat dilakukan segera, operasi akan diblokir
4. Timesout: Jika operasi tidak dapat dilakukan segera, operasi akan diblokir pada waktu yang ditentukan. Jika waktu yang ditentukan tidak dieksekusi, nilai khusus akan dikembalikan, yang biasanya benar atau salah.
Perlu dicatat bahwa kita tidak dapat memasukkan null ke dalam blockingqueue, jika tidak NullPointerException akan dilaporkan.
4. Kelas Implementasi BlockingQueue
BlockingQueue hanyalah sebuah antarmuka dalam paket java.util.concurrent . Saat menggunakannya secara khusus, kami menggunakan kelas implementasinya. Tentu saja, kelas implementasi ini juga terletak di paket java.util.concurrent . Di Java 6, kelas implementasi BlockingQueue terutama sebagai berikut:
1. ArrayBlockingQueue
2. Delayqueue
3. LinkedBlockingQueue
4. PrioritasBlockingQueue
5. Synchronousqueue
Di bawah ini kami akan memperkenalkan kelas implementasi ini secara terpisah.
4.1 ArrayBlockingQueue
ArrayBlockingQueue adalah antrian pemblokiran yang dibatasi, dan implementasinya adalah array. Arti batas berarti bahwa kapasitasnya terbatas, kita harus menentukan ukuran kapasitasnya ketika diinisialisasi, dan ukuran kapasitas tidak dapat diubah setelah ditentukan.
ArrayBlockingQueue menyimpan data secara pertama. Objek yang baru dimasukkan adalah ekor dan objek yang baru dipindahkan adalah kepala. Berikut adalah contoh inisialisasi dan menggunakan arrayblockingqueue:
BlockingQueue Queue = ArrayBlockingQueue baru (1024); Queue.put ("1"); objek objek = queue.take ();4.2 Delayqueue
Blok Delayqueue apa adalah elemen internalnya. Elemen -elemen dalam Delayqueue harus mengimplementasikan antarmuka java.util.concurrent.Delayed . Definisi antarmuka ini sangat sederhana:
Antarmuka publik tertunda memperluas <Delayed> {long getDelay (TimeUnit Unit);} Nilai pengembalian metode getDelay() adalah waktu penahanan sebelum elemen antrian dirilis. Jika 0 atau负值dikembalikan, itu berarti bahwa elemen telah kedaluwarsa dan perlu dilepaskan. Pada saat ini, DelayedQueue akan melepaskan objek ini melalui metode take() .
Seperti dapat dilihat dari definisi antarmuka yang tertunda di atas, ia juga mewarisi antarmuka Comparable . Ini karena elemen -elemen dalam keterlambatan perlu diurutkan. Secara umum, kami mengurutkan berdasarkan prioritas waktu kedaluwarsa elemen.
Contoh 1: Tentukan waktu kedaluwarsa untuk suatu objek
Pertama, kami mendefinisikan elemen, yang perlu menerapkan antarmuka yang tertunda
DelayedElement kelas publik mengimplementasikan {private long kedaluwarsa; penundaan panjang pribadi; nama string pribadi; DelayedElement (String ElementName, Long Delay) {This. name = elementName; ini. tunda = tunda; kedaluwarsa = (tunda + sistem. SurrentTimeMillis ()); } @Override public int compareto (delayed o) {delayedElement cacached = (delayedElement) o; return cached.getExpired ()> kedaluwarsa? 1: -1; } @Override public long getDelay (timeUnit unit) {return (kadaluwarsa - sistem. CurrentTimeMillis ()); } @Override Public String ToString () {return "DelayedElement [delay =" + Delay + ", name =" + name + "]"; } public long getExired () {return kadaluwarsa; }}Atur waktu kedaluwarsa elemen ini ke 3s
Public Class DelayqueEExample {public static void main (string [] args) melempar interruptedException {delayqueue <dllayedElement> queue = new Delayqueue <> (); DelayedElement ELE = DelayedElement baru ("cache 3 detik", 3000); queue.put (ele); Sistem. out.println (queue.take ()); }}Jalankan fungsi utama ini dan kita dapat menemukan bahwa kita perlu menunggu 3 detik sebelum mencetak objek ini.
Bahkan, ada banyak skenario aplikasi untuk DelayQueue, seperti koneksi penutupan waktunya, objek cache, pemrosesan batas waktu dan skenario lainnya. Mari kita ambil ujian siswa sebagai contoh untuk membiarkan semua orang memahami penggunaan DelayQueue lebih dalam.
Contoh 2: Perlakukan semua siswa dalam ujian sebagai penundaan, siapa pun yang menyelesaikan pertanyaan pertama kali melepaskannya
Pertama, kami membangun objek siswa
Mahasiswa kelas publik mengimplementasikan runnable, tertunda {name string pribadi; // Beri nama Private Long Costtime; // Waktu untuk Pertanyaan Tes Private Long Time; // Waktu untuk Penyelesaian Mahasiswa Publik (nama string, waktu biaya panjang) {this. name = name; ini. waktu biaya = biaya biaya; Finishtime = Sistem Costtime +. currentTimemillis (); } @Override public void run () {System. out.println (nama + "Kirim kertas, waktu" + biaya /1000); } @Override public long getDelay (TimeUnit Unit) {return (flealTime - System. CurrentTimeMillis ()); } @Override public int compareto (tertunda o) {student lainnya = (siswa) o; pengembalian biaya> = lainnya. waktu biaya? 1: -1; }}Kemudian, buat objek guru untuk mengikuti ujian kepada siswa
guru kelas publik {static final int student_size = 30; public static void main (string [] args) melempar InterruptedException {acak r = acak baru (); // Pikirkan semua siswa sebagai penundaan penundaan penundaan <spulhy> Siswa = Delayqueue baru <shenwa> (); // Bangun kumpulan utas untuk membiarkan siswa "melakukan pekerjaan rumah mereka" ExecutorService exec = executors.newfixedThreadPool (Student_Size); untuk (int i = 0; i <student_size; i ++) {// menginisialisasi nama dan waktu siswa untuk melakukan tes siswa.put (siswa baru ("siswa" + (i + 1), 3000 + r.nextint (10000))); } // Mulailah tes saat (! Student.isempty ()) {exec.execute (student.take ()); } exec.shutdown (); }}Mari kita lihat hasil berjalan:
Siswa 2 Kirimkan Kertas, 3
Siswa 1 menyerahkan kertas, mengambil 5
Siswa 5 Kirimkan Kertas, 7
Siswa 4 Kirimkan kertas, mengambil 8
Siswa 3 Kirimkan kertas, 11
Melalui hasil berjalan, kita dapat menemukan bahwa setiap siswa akan "mengirimkan kertas" setelah waktu mulai yang ditentukan tiba ( tergantung pada metode getDelay () ), dan kertas akan diserahkan terlebih dahulu ( tergantung pada metode compareTo () ).
Dengan melihat kode sumbernya, Anda dapat melihat bahwa implementasi internal Delayqueue menggunakan prioritas dan kunci:
4.3 LinkedBlockingQueue
Konfigurasi ukuran antrian penghambat LinkedBlockingQueue adalah opsional. Jika kami menentukan ukuran saat menginisialisasi, itu dibatasi, dan jika tidak ditentukan, itu dibatasi. Dikatakan tidak terbatas, tetapi pada kenyataannya, ukuran default adalah Integer.MAX_VALUE kapasitas. Implementasinya adalah daftar yang ditautkan.
Seperti ArrayBlockingQueue, LinkedBlockingQueue juga menyimpan data secara pertama. Objek yang baru dimasukkan adalah ekor dan objek yang baru dipindahkan adalah kepala. Berikut adalah contoh inisialisasi dan membuat LinkedBlockingQueue:
Blockingqueue <string> tidak terikat = LinkedBlockingQueue baru <string> (); blockingqueue <string> terikat = new LinkedBlockequeUe <string> (1024); bounded.put ("value"); string value = bounded.take ();4.4 PrioritasBlockingQueue
PriorityBlockingQueue adalah antrian tanpa batas, dan aturan penyortirannya sama dengan java.util.PriorityQueue . Perlu dicatat bahwa objek nol diizinkan untuk dimasukkan dalam prioritasblockingqueue.
Semua objek yang dimasukkan ke dalam PrioritasBlockingQueue harus mengimplementasikan antarmuka java.lang.Comparable .
Selain itu, kita bisa mendapatkan iterator dari PriorityBlockingQueue, tetapi iterator ini tidak menjamin iterasi dalam urutan prioritas.
Mari kita beri contoh untuk diilustrasikan. Pertama, kami mendefinisikan jenis objek, yang perlu mengimplementasikan antarmuka yang sebanding:
Prioritas kelas publik mengimplementasikan yang sebanding dengan <i prioritas> {private int prioritas; // definisikan prioritas prioritas (int prioritas) {// inisialisasi prioritas this.priority = prioritas;}@overridepublic int compareto (prioritas o) {// sort berdasarkan ukuran prioritas prioritas pengembalian> = o.getrority () {// sort berdasarkan ukuran prioritas prioritas> = o.getPiority () ()? 1: -1;} public int getPriority () {return prioritas;} public void setPriority (int prioritas) {this.priority = prioritas;}@overridepublic string toString () {return "prioritas [prioritas =" + prioritas + "];Kemudian kami secara acak menetapkan prioritas ke antrian
Public Class PriorityBlockingQueueExample {public static void main (string [] args) melempar InterruptedException {PrioritasBlockingQueue <Pi priorityElement> queue = prioritas baruBlockingQueue <> (); untuk (int i = 0; i <5; i ++) {acak acak = acak baru (); Prioritas eLe = prioritas baru (acak.nextint (10)); queue.put (ele); } while (! Queue.isempty ()) {System.out.println (queue.take ()); }}}Lihat hasil berjalan:
PrioritasElement [Prioritas = 3]
PrioritasElement [Prioritas = 4]
PrioritasElement [Prioritas = 5]
PrioritasElement [Prioritas = 8]
PrioritasElement [Prioritas = 9]
4.5 Synchronousqueue
Hanya satu elemen yang diizinkan di dalam antrian synchronousqueue. Ketika utas memasukkan elemen, itu akan diblokir kecuali elemen dikonsumsi oleh utas lain.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.