LinkedBlockingQueue juga dilaksanakan menggunakan senarai terpaut sehala Ia juga mempunyai dua Nod, yang digunakan untuk menyimpan nod pertama dan terakhir, dan terdapat juga kiraan pembolehubah atom dengan nilai awal 0, iaitu. digunakan untuk merekodkan bilangan elemen baris gilir. Terdapat juga dua contoh ReentrantLock, yang digunakan untuk mengawal keatoman unsur-unsur yang masuk dan dequeuing. Antaranya, takeLock digunakan untuk mengawal bahawa hanya satu utas boleh mendapatkan elemen daripada kepala baris gilir pada masa yang sama, dan utas lain mesti. tunggu. PutLock mengawal bahawa hanya satu utas boleh mendapatkan elemen daripada kepala baris gilir pada masa yang sama Satu utas boleh memperoleh kunci dan menambah elemen pada penghujung baris gilir, dan utas lain mesti menunggu. Selain itu, notEmpty dan notFull ialah pembolehubah keadaan Mereka mempunyai baris gilir keadaan dalaman untuk menyimpan benang yang disekat apabila masuk dan keluar dari baris gilir. Berikut ialah kod untuk membuat kunci eksklusif.
private final AtomicInteger count = new AtomicInteger(); /** Lock held by take, poll, etc */ private final ReentrantLock takeLock = new ReentrantLock(); /** Wait queue for waiting takes */ private final Condition notEmpty = takeLock.newCondition(); /** Lock held by put, offer, etc */ private final ReentrantLock putLock = new ReentrantLock(); /** Wait queue for waiting puts */ private final Condition notFull = putLock.newCondition();
Apabila urutan panggilan menjalankan operasi seperti ambil dan tinjauan pendapat pada contoh LinkedBlockingQueue, ia perlu mendapatkan kunci takeLock untuk memastikan hanya satu utas boleh mengendalikan nod kepala bagi senarai terpaut pada masa yang sama. Di samping itu, memandangkan penyelenggaraan baris gilir keadaan di dalam pembolehubah keadaan notEmpty menggunakan mekanisme pengurusan keadaan kunci takeLock, utas panggilan mesti mendapatkan kunci takeLock terlebih dahulu sebelum memanggil kaedah tunggu dan isyarat notEmpty, jika tidak pengecualian IllegalMonitorStateException akan dilemparkan . NotEmpty mengekalkan baris gilir syarat secara dalaman Apabila utas memperoleh takeLock dan memanggil kaedah await notEmpty, utas panggilan akan disekat, dan kemudian utas akan diletakkan dalam baris gilir keadaan di dalam notEmpty untuk menunggu sehingga utas memanggil isyarat notEmpty kaedah.
Apabila melakukan operasi letak, tawaran dan lain-lain pada contoh LinkedBlockingQueue, anda perlu mendapatkan kunci putLock untuk memastikan hanya satu utas boleh mengendalikan nod ekor senarai terpaut pada masa yang sama masa. Begitu juga, memandangkan penyelenggaraan baris gilir keadaan di dalam pembolehubah keadaan notFull menggunakan mekanisme pengurusan keadaan kunci putLock, benang panggilan mesti memperoleh kunci putLock terlebih dahulu sebelum memanggil kaedah menunggu dan isyarat notFull, jika tidak pengecualian IllegalMonitorStateException akan dilemparkan. NotFull mengekalkan baris gilir syarat secara dalaman Apabila utas memperoleh kunci putLock dan memanggil kaedah tunggu notFull, utas panggilan akan disekat, dan kemudian utas akan diletakkan dalam baris gilir syarat di dalam notFull untuk menunggu sehingga utas memanggil notFull. kaedah isyarat. Berikut ialah kod untuk pembina tanpa parameter LinkedBlockingQueue.
Berikut ialah kod pembinaan bebas parameter LinkedBlockingQueue
public static final int MAX_VALUE = 0x7fffffff; public LinkedBlockingQueue() { this(Integer.MAX_VALUE); } public LinkedBlockingQueue(int capacity) { if (capacity <= 0) throw new IllegalAgrumentException(); this.capacity = capacity; last = head = new Node<E>(null); }
Daripada kod ini, kita dapat melihat bahawa kapasiti baris gilir lalai ialah 0x7ffffffff, dan pengguna boleh juga menentukan kapasiti itu sendiri, jadi dari yang tertentu Pada tahap tertentu, boleh dikatakan bahawa LinkedBlockingQueue ialah baris gilir menyekat terhad.
operasi tawaran
public boolean offer(E e) { //(1) if (e == null) throw new NullPointerException(); //(2) final AtomicInteger count = this.count; if (count.get() == capacity) return false; //(3) int c = -1; Node<E> node = new Node<E>(e); final ReentrantLock putLock = this.putLock; putLock.lock(); try { //(4) if (count.get() < capacity) { enqueue(node); c = count.getAndIncrement(); //(5) if (c + 1 < capacity) notFull.signal(); } } finally { //(6) putLock.unlock(); } //(7) if (c == 0) signalNotEmpty(); //(8) return c >= 0; }
Kod (2) menentukan sama ada baris gilir semasa penuh, buang elemen semasa dan kembali palsu
Kod ( 3) Selepas kunci putLock diperoleh, selepas benang semasa memperoleh kunci, benang lain yang memanggil operasi put dan tawaran akan disekat (benang yang disekat akan diletakkan dalam baris gilir penyekat AQS bagi kunci putLock).
Kod (4) menilai semula sama ada baris gilir semasa penuh Ini kerana urutan lain mungkin telah menambah elemen baharu pada baris gilir melalui operasi letak atau tawaran semasa pelaksanaan kod (2) dan pemerolehan. kunci putLock. Jika baris gilir memang tidak penuh, elemen baharu akan ditambah pada baris gilir dan kaunter akan ditambah.
Kod (5) menentukan bahawa jika masih terdapat ruang kosong dalam baris gilir selepas elemen baharu ditambahkan pada baris gilir, baris gilir bersyarat notFull akan terjaga kerana operasi tunggu notFull dipanggil (seperti apabila kaedah put dilaksanakan dan baris gilir penuh). Benang yang disekat boleh membangunkan benang beratur lebih awal kerana baris gilir kini bebas.
Kod (6) melepaskan kunci putLock yang diperoleh Perlu diingatkan di sini bahawa pelepasan kunci mesti dilakukan pada akhirnya kerana walaupun blok cuba melemparkan pengecualian, akhirnya akan dilaksanakan. Di samping itu, selepas kunci dilepaskan, salah satu daripada benang lain yang disekat kerana memanggil operasi meletakkan akan memperoleh kunci.
C0 dalam kod (7) menunjukkan bahawa terdapat sekurang-kurangnya satu elemen dalam baris gilir semasa melaksanakan kod (6) untuk melepaskan kunci Jika terdapat elemen dalam baris gilir, operasi signalNotEmpty dilakukan.
Atas ialah kandungan terperinci Bagaimana untuk menggunakan baris gilir LinkedBlockingQueue dalam pengaturcaraan serentak Java?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!