1. ما هي قائمة انتظار الحظر؟
قائمة الانتظار عبارة عن بنية بيانات لها عمليتان أساسيتان: إضافة عنصر في نهاية قائمة الانتظار وإزالة عنصر من رأس قائمة الانتظار. الفرق بين حظر الفرق والقوائم العادية هو أن قوائم الانتظار العادية لن تمنع الخيط الحالي. عند مواجهة نماذج منتجات مستهلك مماثلة ، يجب تنفيذ استراتيجيات التزامن الإضافية واستراتيجيات الاستيقاظ بين الخيوط. سيؤدي استخدام قائمة انتظار الحظر إلى حظر الخيط الحالي. عندما تكون قائمة الانتظار فارغة ، سيتم حظر تشغيل عناصر من قائمة الانتظار. عندما تكون قائمة الانتظار ممتلئة ، سيتم أيضًا حظر تشغيل العناصر إلى قائمة الانتظار.
2. قائمة انتظار الحظر الرئيسية وطرقها
توفر حزمة java.util.concurrent العديد من قوائم الحجب الرئيسية ، بشكل رئيسي على النحو التالي:
1) ArrayBlockingQueue: قائمة انتظار الحظر على أساس تنفيذ الصفيف. عند إنشاء كائن arrayblockingqueue ، يجب تحديد قدرته. يمكن أيضًا تحديده لسياسات الوصول. بشكل افتراضي ، ليس من العدل ، أي أنه لا يضمن أن يكون لخيط مع أطول وقت انتظار قادر على الوصول إلى قائمة الانتظار أولاً.
2) LinkedBlockingQueue: قائمة انتظار الحظر بناءً على قائمة مرتبطة. إذا لم يتم تحديد حجم السعة عند إنشاء كائن LinkedBlockingQueue ، فإن الحجم الافتراضي هو integer.max_value.
3) قوائم الانتظار المذكورة أعلاه هي أول قوائم في قائمة الانتظار الأولى ، لكن PriorityBlockingqueue ليست كذلك. سوف يقوم بفرز العناصر وفقًا لأولوية العناصر و dequeue في ترتيب الأولوية. كل عنصر dequeue هو العنصر الأولوية الأعلى. لاحظ أن قائمة انتظار الحظر هذه عبارة عن قائمة انتظار حظر غير محدودة ، أي أنه لا يوجد حد أعلى على السعة (يمكنك معرفة من خلال الكود المصدري أنه لا يحتوي على علامة إشارة مليئة بالحاوية). النوعين الأولين محددون في قوائم الانتظار.
4) تأخير: استنادًا إلى أولوية ، قائمة انتظار حظر التأخير. لا يمكن للعنصر في التأخير الحصول على العنصر فقط من قائمة الانتظار عند الوصول إلى وقت التأخير المحدد. يعد Develiqueue أيضًا قائمة انتظار غير محدودة ، وبالتالي فإن عملية (منتج) إدخال البيانات في قائمة الانتظار لن يتم حظرها أبدًا ، وسيتم حظر عملية الحصول على البيانات (المستهلك) فقط.
تتضمن قوائم انتظار الحظر معظم الطرق في قوائم الانتظار غير الحظر ، وتوفير العديد من الطرق الأخرى المفيدة للغاية:
يتم استخدام طريقة PUT لتخزين العناصر في ذيل قائمة الانتظار ، وإذا كانت قائمة الانتظار ممتلئة ، فانتظر ؛
يتم استخدام طريقة Take للحصول على عناصر من قائمة الانتظار ، وإذا كانت قائمة الانتظار فارغة ، فانتظر ؛
يتم استخدام طريقة العرض لتخزين العناصر في ذيل قائمة الانتظار. إذا كانت قائمة الانتظار ممتلئة ، فسوف تنتظر وقتًا معينًا. عندما يتم الوصول إلى الفترة الزمنية ، إذا لم يكن الإدراج ناجحًا ، فسوف يعود خطأ ؛ وإلا فإنه سيعود صحيحًا ؛
يتم استخدام طريقة الاستطلاع للحصول على عناصر من قائمة الانتظار الأولى. إذا كانت قائمة الانتظار فارغة ، فسوف تنتظر وقتًا معينًا. عندما يتم الوصول إلى الفترة الزمنية ، إذا تم استردادها ، فسوف تعود فارغة ؛ خلاف ذلك ، سوف يعيد العنصر الذي تم الحصول عليه ؛
هنا رمز:
استيراد java.util.concurrent.arrayBlocking ؛/** * Author المؤلف: Xu Jiane-mail: anea_2013.com * @Varvent تم إنشاؤه: 20 مارس 2016 ، الساعة 12:52:53 PM * Class Description */public class plockingqueue java.util.concurrent.blockingqueue <string> blockingqueue = new ArrayBlockingQueue <> (5) ؛ لـ (int i = 0 ؛ i <10 ؛ i ++) {// أضف العنصر المحدد إلى هذا قائمة الانتظار blockingqueue.put ("add element"+i) ؛ System.out.println ("العنصر المضافة إلى قائمة انتظار الحظر:" + i) ؛ } system.out.println ("ينتهي البرنامج هذه المرة وسيخرج ----") ؛ }}عندما يكون عدد قوائم انتظار حظر الحد 5 ، بعد إضافة 5 عناصر ، سيتم حظر العملية خارج قائمة الانتظار والانتظار ، ولا ينتهي البرنامج في هذا الوقت.
عندما تكون قائمة الانتظار ممتلئة ، نقوم بإزالة عنصر الرأس ويمكننا الاستمرار في إضافة عناصر إلى قائمة انتظار الحظر. الرمز كما يلي:
فئة عامة blockingqueue {public static void main (string [] args) remrows interruptedException {java.util.concurrent.blockingqueue <string> blockingqueue = new ArrayBlockingqueue <> (5) ؛ لـ (int i = 0 ؛ i <10 ؛ i ++) {// أضف العنصر المحدد إلى هذا قائمة الانتظار blockingqueue.put ("add element"+i) ؛ System.out.println ("العنصر المضافة إلى قائمة انتظار الحظر:" + i) ؛ if (i> = 4) system.out.println ("قم بإزالة عنصر الرأس" +blockingqueue.take ()) ؛ } system.out.println ("ينتهي البرنامج هذه المرة وسيخرج ----") ؛ }نتائج التنفيذ هي كما يلي:
3. مبدأ التنفيذ لحظر قائمة الانتظار <BR /> يلي ما يلي بشكل أساسي في مبدأ التنفيذ لـ ArrayBlockingQueue.
أولاً ، دعونا نلقي نظرة على متغيرات الأعضاء في فئة ArrayBlockingQueue:
الطبقة العامة arrayblockingqueue <e> يمتد مجردة <e> تنفذ blockingqueue <e> ، java.io.serializable { / ** array-array-array* / final object [] ؛ / ** عنصر رئيس الفريق subcript*/ int takeindex ؛ / ** Team Tail Element Subcript*/ int putIndex ؛ / ** إجمالي عدد عناصر قائمة الانتظار*/ int / ** reentrantlock*/ final reentrantlock lock ؛ / ** حالة الانتظار غير المألوفة*/ الشرط النهائي الخاص / ** حالة الانتظار notfull*/ الشرط النهائي الخاص nustfull ؛ /** * الحالة المشتركة للمترجمين النشطين حاليًا ، أو NULL إذا كان هناك * معروفًا بعدم وجود أي. يسمح لعمليات قائمة الانتظار بتحديث * حالة Iterator. */ عابرة ITRS ITRS = فارغة ؛كما ترون ، فإن ArrayBlockingQueue المستخدم لتخزين العناصر هو في الواقع صفيف.
دعونا نلقي نظرة على تنفيذ طريقتين مهمتين لـ ArrayBlockingQueue و Put () و Take ():
Public void put (e e) رميات interruptedException {// تحقق أولاً مما إذا كانت e فارغة checkNotnull (e) ؛ // الحصول على قفل القفل النهائي reentrantlock قفل = this.lock ؛ lock.lockInterruptly () ؛ جرب {// عندما تكون قائمة الانتظار ممتلئة ، أدخل الشرط وانتظر بينما (count == items.length) notull.await () ؛ // قائمة الانتظار غير راضية ، وأداء عملية قائمة الانتظار enqueue (e) ؛ } أخيرًا {// refer the lock.unlock () ؛ }} دعونا نلقي نظرة على عملية الانضمام المحددة:
private void enqueue (e x) {final object [] items = this.items ؛ // عناصر endermination [putIndex] = x ؛ if (++ putIndex == items.length) putIndex = 0 ؛ // إجمالي عدد قوائم الانتظار +1 count ++ ؛ // حدد مؤشر ترابط بشكل عشوائي في مجموعة الانتظار لحالة غير المألوفة لإلغاء حظر حالة الحجب. } فيما يلي رمز المصدر لطريقة take ():
public e take () رميات interruptedException {// الحصول على قفل القفل النهائي reentrantlock = this.lock ؛ lock.lockInterruptly () ؛ جرب {// قائمة الانتظار فارغة بينما (count == 0) // ينضم مؤشر الترابط إلى حالة انتظار حالة عدم التخلص من notempty.await () ؛ // غير فارغ ، الخروج من قائمة الانتظار dequeue () ؛ } أخيرًا {// refer the lock.unlock () ؛ }} 4. تطبيق قوائم انتظار حظر: تنفيذ نموذج منتج المستهلك
/** * Author المؤلف: Xu Jiane-Mail: [email protected] * version إنشاء الوقت: 20 مارس ، 2016 في 2:21:55 PM * الوصف: وضع المنتج المستهلك الذي تم تنفيذه عن طريق منع قائمة الانتظار */اختبار الفئة العامة {private int queuesize = 10 ؛ arrayblockingqueue <seger> Queue = new ArrayBlockingQueue <integer> (queueSize) ؛ public static void main (string [] args) {test test = new test () ؛ منتج المنتج = test.new producer () ؛ المستهلك المستهلك = test.new consumer () ؛ Producer.start () ؛ المستهلك. } Class Consumer يمتد Thread {Override public void run () {consumpt () ؛ } private void consumpt () {when (true) {try {queue.take () ؛ System.out.println ("خذ عنصرًا من قائمة الانتظار ، ويبقى قائمة الانتظار" + queue.size () + "عناصر") ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }}}} Class Producer يمتد Thread {Override public void run () {prode () ؛ } Private void produce () {بينما (true) {try {queue.put (1) ؛ System.out.println ("أدخل عنصرًا في قائمة الانتظار ، المساحة المتبقية في قائمة الانتظار:"+ (QueUeSize - Queue.size ())) ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }}}}}}
ما سبق هو كل شيء عن هذا المقال ، آمل أن يكون مفيدًا لتعلم الجميع.