منع قوائم الانتظار في جافا
1. ما هي قائمة انتظار الحظر؟
قائمة انتظار الحظر (blockingqueue) عبارة عن قائمة انتظار تدعم عمليتين إضافيتين. هاتان العمليتان الإضافيتان هما:
عندما تكون قائمة الانتظار فارغة ، فإن الخيط الذي يجلب العنصر ينتظر أن يصبح قائمة الانتظار غير فارغة.
عندما تكون قائمة الانتظار ممتلئة ، سينتظر الخيط الذي يخزن العناصر حتى يتوفر قائمة الانتظار.
غالبًا ما يتم استخدام قوائم الانتظار في سيناريوهات المنتجين والمستهلكين. المنتجون هم مؤشرات ترابط يضيفون عناصر إلى قوائم الانتظار ، والمستهلكين هم مؤشرات ترابط يأخذ عناصر من قوائم الانتظار. قائمة انتظار الحظر هي الحاوية التي يخزن فيها المنتج عناصر ، ويأخذ المستهلك فقط عناصر من الحاوية.
2. حظر قائمة الانتظار في جافا
يتم توفير سبع قوائم انتظار في JDK:
arrayblockingqueue
ArrayBlockingQueue هو قائمة انتظار حظر محددة يتم تنفيذها باستخدام المصفوفات. تقوم قائمة الانتظار هذه بفرز العناصر وفقًا لمبدأ الأول في أول (FIFO). افتراضيًا ، لا يضمن الزوار للوصول إلى حد ما. يشير ما يسمى قائمة الانتظار التي يمكن الوصول إليها إلى حد ما إلى جميع مؤشرات ترابط المنتج المحظورة أو مؤشرات الترابط المستهلك. عند توفر قائمة الانتظار ، يمكن الوصول إلى قائمة الانتظار بترتيب الحظر. بمعنى ، يمكن لخيط المنتج الذي يحظر أولاً إدراج العناصر في قائمة الانتظار أولاً ، ويمكن لخيط المستهلك الذي يحظر أولاً الحصول على عناصر من قائمة الانتظار أولاً. عادة ، يتم تقليل الإنتاجية من أجل ضمان الإنصاف . يمكننا إنشاء قائمة انتظار حظر عادلة باستخدام الرمز التالي:
ArrayBlockingQueue fairqueue = new ArrayBlockingQueue (1000 ، true) ؛
يتم تحقيق إنصاف وصوله من خلال قفل reentrantlock.
LinkedBlockingqueue
LinkedBlockingQueue هو قائمة انتظار حظر محددة يتم تنفيذها مع قوائم مرتبطة. الافتراضي والطول القصوى من قائمة الانتظار هذا هو integer.max_value. تقوم قائمة الانتظار بفرز العناصر وفقًا لمبدأ الأول في الأول.
priorityblockingqueue
PriorityBlockingQueue هو قائمة انتظار غير محدودة تدعم الأولوية. بشكل افتراضي ، يتم ترتيب العناصر بالترتيب الطبيعي ، ويمكن أيضًا تحديد قواعد الطلب للعناصر من خلال مقارنة المقارنة. يتم ترتيب العناصر في ترتيب تصاعدي.
تأخير
Develiqueue هو قائمة انتظار حظر غير محدودة تدعم تأخر الاستحواذ على العناصر. يتم تنفيذ قائمة الانتظار باستخدام PriorityQueue. يجب أن تنفذ العناصر الموجودة في قائمة الانتظار الواجهة المتأخرة ، وعند إنشاء عنصر ، يمكنك تحديد المدة التي يستغرقها الحصول على العنصر الحالي من قائمة الانتظار. لا يمكن استخراج العناصر إلا من قائمة الانتظار عندما ينتهي التأخير. يمكننا استخدام التأخير في سيناريوهات التطبيق التالية:
تصميم نظام ذاكرة التخزين المؤقت: يمكن استخدام DelayQueue لحفظ فترة صحة عناصر ذاكرة التخزين المؤقت ، ويمكن استخدام مؤشر ترابط للاستعلام عن التأخير. بمجرد الحصول على العنصر من تأخير ، يعني أن فترة صحة ذاكرة التخزين المؤقت قد وصلت.
جدول المهام المجدول. استخدم Develiqueue لحفظ المهام ووقت التنفيذ الذي سيتم تنفيذه في اليوم. بمجرد الحصول على المهمة من Develiqueue ، ستبدأ في التنفيذ. على سبيل المثال ، يتم تنفيذ TimerQueue باستخدام Develophqueue.
كيفية تنفيذ الواجهة المتأخرة
يمكننا الرجوع إلى فئة ScheduleDFutureTask في SecretThreadPoolExecutor. هذه الفئة تنفذ الواجهة المتأخرة. أولاً: عند إنشاء كائن ، استخدم الوقت لتسجيل متى يمكن استخدام الكائن قبل التسجيل. الرمز كما يلي:
ScheduleDfutureTask (Runnable R ، V Result ، Long NS ، فترة طويلة) {super (r ، result) ؛ this.time = ns ؛ this.period = الفترة ؛ this.quencenber = sequencer.getandincrement () ؛}ثم استخدم GetDelay للاستعلام عن المدة التي يحتاج فيها العنصر الحالي إلى تأخير. الرمز كما يلي:
Public Long GetDelay (timeUnit Unit) {return unit.convert (time - now () ، timeUnit.nanoseconds) ؛ }من خلال المنشئ ، يمكننا أن نرى أن وحدة معلمة وقت التأخير NS هي النانو ثانية. من الأفضل استخدام النانو ثانية عند تصميمها بنفسك ، لأنه يمكنك تحديد أي وحدة عند الحصول على الحصول على. بمجرد استخدام النانو ثانية كوحدة ، ووقت التأخير أقل من النانو ثانية ، سيكون الأمر مزعجًا. عند الاستخدام ، يرجى ملاحظة أنه عندما يكون الوقت أقل من الوقت الحالي ، ستعيد GetDelay رقمًا سلبيًا.
أخيرًا ، يمكننا استخدام الوقت لتحديد الطلب في قائمة الانتظار ، على سبيل المثال: دع أطول وقت تأخير يتم وضعه في نهاية قائمة الانتظار.
public int compareto (تأخر الآخر) {if (other == this) return 0 ؛ if (existance Other ScheduleDfutureTask) {ScheduleDfutureTask x = (ScheduleDFutureTask) Other ؛ diff long = time - x.time ؛ إذا (diff <0) return -1 ؛ وإلا إذا (diff> 0) return 1 ؛ وإلا عودة أخرى 1 ؛ } long d = (getDelay (timeUnit.nanoSeconds) -Oled.getDelay (timeUnit.nanoseconds)) ؛ العودة (د == 0)؟ 0: ((D <0)؟ -1: 1) ؛ }كيفية تنفيذ طوابير حظر تأخير
تطبيق قوائم انتظار حظر التأخير أمر بسيط للغاية. عندما يحصل المستهلك على عناصر من قائمة الانتظار ، إذا لم يصل العنصر إلى وقت التأخير ، فإنه يحظر الخيط الحالي.
تأخير طويل = first.getDelay (timeUtil.nanoseconds) ؛ if (تأخير <= 0) {return q.poll ؛ // حظر قائمة الانتظار} آخر if (Leader! = null) {// lead يمثل مؤشر ترابط في انتظار رسالة من قائمة انتظار الحظر المتاحة. // دع مؤشر الترابط يدخل إشارة الانتظار} else {// عندما يكون القائد خاليًا ، قم بتعيين مؤشر الترابط الحالي على ThisThread = thread.currentThRead () ؛ حاول {Leader = thisthread ؛ // استخدم طريقة Awaitnanos () لجعل مؤشر الترابط الحالي ينتظر الإشارة المستلمة أو انتظار وقت التأخير المتاح. }}}متزامن
Synchronousqueue هو قائمة انتظار الحظر التي لا تخزن العناصر. يجب أن تنتظر كل عملية وضع عملية ، وإلا لا يمكن إضافة العناصر. يمكن اعتبار Synchronousqueue مارة ، مسؤولة عن تمرير البيانات التي تتم معالجتها بواسطة مؤشر ترابط المنتج مباشرة إلى مؤشر ترابط المستهلك. قائمة الانتظار نفسها لا تخزن أي عناصر ، وهي مناسبة جدًا للسيناريوهات المتعدية. على سبيل المثال ، يتم تمرير البيانات المستخدمة في مؤشر ترابط واحد إلى مؤشر ترابط آخر للاستخدام. إنتاجية متزامنة أعلى من ذلك
LinkedBlockingQueue و ArrayBlockingqueue.
وهو يدعم قوائم انتظار الوصول العادلة. افتراضيًا ، لا تزال آلية سياسة غير عادلة
LinkedTransferqueue
LinkedTransferqueue هي قائمة انتظار نقل غير محدودة مملوكة تتكون من بنية قائمة مرتبطة. مقارنة بقوائم الحظر الأخرى ، لدى LinkedTransferqueue المزيد من طرق TryTransfer و Transfer.
طريقة النقل
إذا كان المستهلك ينتظر حاليًا لتلقي عنصر (عندما يستخدم المستهلك طريقة Take () أو طريقة الاستطلاع المحدودة للوقت) ، فيمكن طريقة النقل على الفور نقل العناصر التي يمررها المنتج إلى المستهلك. إذا لم يكن أي مستهلك ينتظر عنصر الاستقبال ، فإن طريقة النقل تخزن العنصر في عقدة الذيل في قائمة الانتظار وينتظر حتى يستهلك المستهلك العنصر قبل العودة.
طريقة trytransfer
يتم استخدامه لاختبار ما إذا كانت العناصر التي يقدمها المنتج يمكن أن تنتقل مباشرة إلى المستهلك. إذا لم يكن أي مستهلك ينتظر عنصر الاستلام ، فسيتم إرجاع خطأ. الفرق بين طريقة النقل هو أن طريقة trytransfer تعود على الفور بغض النظر عما إذا كان المستهلك يتلقى ذلك أم لا. يجب أن تنتظر طريقة النقل حتى يستهلك المستهلك قبل العودة.
بالنسبة لطريقة Trytransfer (E e ، ant timeout ، وحدة الوقت المحدد) مع الحد الزمني ، فإنها تحاول تمرير العنصر الذي يمرره المنتج مباشرة إلى المستهلك ، ولكن إذا لم يكن هناك مستهلك يستهلك العنصر ، فسوف ينتظر الوقت المحدد قبل العودة. إذا لم تستهلك المهلة العنصر ، فسيتم إرجاعها خطأ ، وإذا تم استهلاك العنصر خلال فترة المهلة ، فسوف يعود بشكل صحيح.
LinkedBlockingDeque
LinkedBlockingDeque عبارة عن قائمة انتظار حظر ثنائية الاتجاه تتكون من بنية قائمة مرتبطة. يشير ما يسمى قائمة الانتظار في اتجاهين إلى حقيقة أنه يمكنك إدراج وإزالة العناصر من كلا طرفي قائمة الانتظار. نظرًا لأن قائمة الانتظار المزدوجة تحتوي على إدخال إضافي إلى قائمة انتظار التشغيل ، يتم تقليل المنافسة بمقدار النصف عندما تنضم مؤشرات ترابط متعددة إلى قائمة الانتظار في نفس الوقت. بالمقارنة مع قوائم انتظار الحظر الأخرى ، يحتوي LinkedBlockingDeque على المزيد من الإضافات ، AddLast ، العرض ، العرض ، Peekfirst ، Peeklast وطرق أخرى. تنتهي الطريقة بالكلمة الأولى ، تشير إلى الإدراج أو الاستحواذ أو إزالة العنصر الأول من قائمة الانتظار المزدوجة. طريقة تنتهي بالكلمة الأخيرة ، مما يشير إلى أن العنصر الأخير من قائمة الانتظار المزدوجة يتم إدخاله أو الحصول عليه أو إزالته. بالإضافة إلى ذلك ، فإن طريقة الإدراج إضافة مكافئة لـ AddLast ، وتكون طريقة إزالة الإزالة مكافئة لـ RemoveFirst. ومع ذلك ، فإن طريقة أخذ تعادل Takefirst. لا أعرف ما إذا كان خطأ في JDK ، ومن الواضح أن استخدام الطريقة مع اللواحق الأولى والأخيرة عند استخدامها. يمكن تهيئة سعة قائمة الانتظار عند تهيئة LinkedBlockingDeque لمنعها من التورم عند إعادة تعزيزها. بالإضافة إلى ذلك ، يمكن استخدام قائمة انتظار الحظر ثنائية الاتجاه في وضع "سرقة العمل".
شكرا لك على القراءة ، آمل أن تساعدك. شكرا لك على دعمك لهذا الموقع!