Memblokir antrian di java
1. Apa itu antrian pemblokiran?
Antrian pemblokiran (BlockingQueue) adalah antrian yang mendukung dua operasi tambahan. Dua operasi tambahan ini adalah:
Ketika antrian kosong, utas yang mengambil elemen akan menunggu antrian menjadi tidak kosong.
Saat antrian penuh, utas yang menyimpan elemen akan menunggu antrian tersedia.
Antrian memblokir sering digunakan dalam skenario produsen dan konsumen. Produsen adalah utas yang menambah elemen ke antrian, dan konsumen adalah utas yang mengambil elemen dari antrian. Antrian pemblokiran adalah wadah tempat produser menyimpan elemen, dan konsumen hanya mengambil elemen dari wadah.
2. Antrian Memblokir di Java
Tujuh antrian pemblokiran disediakan di JDK:
Arrayblockingqueue
ArrayBlockingQueue adalah antrian pemblokiran terikat yang diimplementasikan menggunakan array. Antrian ini mengurutkan elemen sesuai dengan prinsip pertama dalam-pertama (FIFO). Secara default, pengunjung tidak dijamin akan mengakses secara adil. Yang disebut antrian yang cukup dapat diakses mengacu pada semua utas produsen yang diblokir atau utas konsumen. Ketika antrian tersedia, antrian dapat diakses dalam urutan pemblokiran. Artinya, utas produsen yang memblokir pertama dapat memasukkan elemen ke dalam antrian terlebih dahulu, dan utas konsumen yang blok pertama dapat memperoleh elemen dari antrian terlebih dahulu. Biasanya, throughput dikurangi untuk memastikan keadilan . Kita dapat membuat antrian pemblokiran yang adil menggunakan kode berikut:
Arrayblockingqueue fairqueue = arrayblockingqueue baru (1000, true);
Keadilan aksesnya dicapai melalui kunci reentrantlock.
LinkedBlockingQueue
LinkedBlockingQueue adalah antrian pemblokiran terikat yang diimplementasikan dengan daftar tertaut. Panjang default dan maksimum antrian ini adalah integer.max_value. Antrian ini mengurutkan elemen sesuai dengan prinsip pertama di pertama.
PrioritasBlockingQueue
PriorityBlockingQueue adalah antrian tak terbatas yang mendukung prioritas. Secara default, elemen diatur dalam urutan alami, dan aturan pemesanan elemen juga dapat ditentukan melalui pembanding pembanding. Elemen -elemen diatur dalam urutan naik.
Delayqueue
Delayqueue adalah antrian pemblokiran yang tidak terbatas yang mendukung akuisisi elemen yang tertunda. Antrian diimplementasikan menggunakan prioritas. Elemen dalam antrian harus mengimplementasikan antarmuka yang tertunda, dan saat membuat elemen, Anda dapat menentukan berapa lama untuk mendapatkan elemen saat ini dari antrian. Elemen hanya dapat diekstraksi dari antrian ketika penundaan berakhir. Kami dapat menggunakan DelayQueue dalam skenario aplikasi berikut:
Desain Sistem Cache: Delayqueue dapat digunakan untuk menghemat periode validitas elemen cache, dan utas dapat digunakan untuk menanyakan Delayqueue. Setelah elemen dapat diperoleh dari Delayqueue, itu berarti bahwa periode validitas cache telah tiba.
Jadwal tugas yang dijadwalkan. Gunakan Delayqueue untuk menyimpan tugas dan waktu eksekusi yang akan dieksekusi pada hari itu. Setelah tugas diperoleh dari Delayqueue, ia akan mulai mengeksekusi. Misalnya, TimerQueue diimplementasikan menggunakan Delayqueue.
Cara mengimplementasikan antarmuka yang tertunda
Kami dapat merujuk ke kelas TerjadwalFutureTask di JadwalTHreadPoolExecutor. Kelas ini mengimplementasikan antarmuka yang tertunda. Pertama: Saat membuat objek, gunakan waktu untuk merekam kapan objek dapat digunakan sebelum merekam. Kodenya adalah sebagai berikut:
TerjadwalFutureTask (hasil runnable r, v, ns panjang, periode panjang) {super (r, hasil); this.time = ns; this.period = periode; this.sequenceNumber = sequencer.getAndIncrement ();}Kemudian gunakan GetDelay untuk menanyakan berapa lama elemen saat ini perlu ditunda. Kodenya adalah sebagai berikut:
publik long getDelay (timeunit unit) {return unit.convert (time - now (), timeunit.nanoseconds); }Melalui konstruktor, kita dapat melihat bahwa unit parameter waktu tunda adalah nanodetik. Yang terbaik adalah menggunakan nanoseconds saat mendesainnya sendiri, karena Anda dapat menentukan unit apa pun saat mendapatkandelay. Setelah nanodetik digunakan sebagai unit, dan waktu tunda kurang dari nanoseconds, itu akan merepotkan. Saat menggunakan, harap dicatat bahwa ketika waktunya kurang dari waktu saat ini, GetDelay akan mengembalikan angka negatif.
Akhirnya, kita dapat menggunakan waktu untuk menentukan urutan dalam antrian, misalnya: Biarkan waktu tunda terpanjang ditempatkan di akhir antrian.
compareTo int publik (tertunda lainnya) {if (lainnya == this) return 0; if (instance lain dari StorduledFutureTask) {StorduledFutureTask x = (StorduledFutureTask) Lainnya; Long Diff = Time - X.Time; if (diff <0) return -1; lain jika (diff> 0) mengembalikan 1; lain jika (sequencenumber <x.sequencenumber) return -1; lain kembali 1; } long d = (getDelay (timeunit.nanoseconds) -other.getDelay (timeunit.nanoseconds)); return (d == 0)? 0: ((d <0)? -1: 1); }Cara menerapkan antrian pemblokiran tertunda
Implementasi antrian pemblokiran penundaan sangat sederhana. Ketika konsumen memperoleh elemen dari antrian, jika elemen tidak mencapai waktu tunda, ia memblokir utas saat ini.
Long Delay = first.getDelay (timeutil.nanoseconds); if (tunda <= 0) {return q.poll; // blocking antreue} lain jika (pemimpin! = null) {// lead mewakili utas yang menunggu pesan dari antrian blocking tersedia.AWAIT (); // Biarkan utas memasukkan sinyal tunggu} else {// Ketika pemimpinnya nol, atur utas saat ini ke leaderThread thesThread = thread.currentThread (); coba {leader = thisthread; // Gunakan metode AWAITNANOS (); }}}Synchronousqueue
Synchronousqueue adalah antrian pemblokiran yang tidak menyimpan elemen. Setiap operasi put harus menunggu operasi, jika tidak elemen tidak dapat ditambahkan. Synchronousqueue dapat dianggap sebagai pelintas, yang bertanggung jawab untuk menyampaikan data yang diproses oleh utas produsen langsung ke utas konsumen. Antrian itu sendiri tidak menyimpan elemen apa pun, yang sangat cocok untuk skenario transitif. Misalnya, data yang digunakan dalam satu utas diteruskan ke utas lain untuk digunakan. Throughput dari sinkron lebih tinggi dari
LinkedBlockingQueue dan ArrayBlockingQueue.
Ini mendukung antrian akses yang adil. Secara default, ini masih merupakan mekanisme kebijakan yang tidak adil
LinkedTransferqueue
LinkedTransferqueue adalah antrian transfer rtransfer yang tidak terbatas yang terdiri dari struktur daftar tertaut. Dibandingkan dengan antrian pemblokiran lainnya, LinkedTransferqueue memiliki lebih banyak metode trytransfer dan transfer.
Metode transfer
Jika konsumen saat ini menunggu untuk menerima elemen (ketika konsumen menggunakan metode ambil () atau metode jajak pendapat terbatas waktu), metode transfer dapat segera mentransfer elemen yang dilewati oleh produsen ke konsumen. Jika tidak ada konsumen yang menunggu elemen penerima, metode transfer menyimpan elemen di simpul ekor antrian dan menunggu sampai elemen dikonsumsi oleh konsumen sebelum kembali.
Metode trytransfer
Ini digunakan untuk menguji apakah elemen yang diperkenalkan oleh produsen dapat secara langsung ditransmisikan ke konsumen. Jika tidak ada konsumen yang menunggu elemen penerima, False dikembalikan. Perbedaan antara metode transfer adalah bahwa metode trytransfer segera kembali terlepas dari apakah konsumen menerimanya atau tidak. Metode transfer harus menunggu sampai konsumen mengonsumsinya sebelum kembali.
Untuk metode trytransfer (e e, jual waktu lama, unit timeunit) dengan batas waktu, ia mencoba untuk lulus elemen yang ditularkan oleh produsen langsung ke konsumen, tetapi jika tidak ada konsumen yang mengonsumsi elemen, ia akan menunggu waktu yang ditentukan sebelum kembali. Jika batas waktu belum mengkonsumsi elemen, itu akan mengembalikan false, dan jika elemen dikonsumsi dalam waktu batas waktu, itu akan mengembalikan true.
LinkedBlockingDeque
LinkedBlockingDeque adalah antrian pemblokiran dua arah yang terdiri dari struktur daftar tertaut. Antrian dua arah yang disebut mengacu pada fakta bahwa Anda dapat memasukkan dan menghapus elemen dari kedua ujung antrian. Karena antrian ujung ganda memiliki entri tambahan untuk antrian operasi, kompetisi dikurangi setengah ketika beberapa utas bergabung dengan antrian pada saat yang sama. Dibandingkan dengan antrian pemblokiran lainnya, LinkedBlockingDeque memiliki lebih banyak addFirst, addLast, Offerfirst, OffestLast, PeekFirst, Peeklast, dan metode lainnya. Metode ini berakhir dengan kata pertama, menunjukkan penyisipan, akuisisi, atau penghapusan elemen pertama dari antrian ujung ganda. Metode yang diakhiri dengan kata terakhir, menunjukkan bahwa elemen terakhir dari antrian endapan ganda dimasukkan, diperoleh atau dihapus. Selain itu, metode penyisipan menambahkan setara dengan addLast, dan metode penghapusan lepas setara dengan menghapus pertama. Namun, metode Take setara dengan TakeFirst. Saya tidak tahu apakah itu bug di JDK, dan lebih jelas menggunakan metode ini dengan sufiks pertama dan terakhir saat menggunakannya. Kapasitas antrian dapat diinisialisasi ketika menginisialisasi LinkedBlockingDeque untuk mencegahnya membengkak ketika ditegaskan kembali. Selain itu, antrian pemblokiran dua arah dapat digunakan dalam mode "pencurian kerja".
Terima kasih telah membaca, saya harap ini dapat membantu Anda. Terima kasih atas dukungan Anda untuk situs ini!