ما هو Thread-Safe BlockingQueue في جافا؟ متى يجب استخدامه؟ التنفيذ مرفق
نشرت: 2021-04-30
لقد كتبت حتى الآن مقالتين عن مفهوم Producer Consumer على Crunchify. الأول لشرح Java Semaphore و Mutex والثاني لشرح القراءة / الكتابة المتزامنة.
في هذا البرنامج التعليمي لجافا سننتقل إلى نفس مفهوم المُنتِج / المستهلك لشرح قائمة BlockingQueue in Java
.
ما هي مزايا حظر قائمة الانتظار في جافا؟
يدعم java.util.Queue
العمليات التي تنتظر حتى تصبح قائمة الانتظار غير فارغة عند استرداد عنصر ، وتنتظر حتى تصبح المساحة متوفرة في قائمة الانتظار عند تخزين عنصر.

نحتاج إلى إنشاء أربع فئات Java:
- CrunchifyMessage.java لوضع الرسائل والحصول عليها
- CrunchifyBlockingProducer.java لوضع الرسالة في قائمة الانتظار
- CrunchifyBlockingConsumer.java للحصول على رسالة من قائمة الانتظار
- CrunchifyBlockingMain.java لبدء الاختبار
عمليات تنفيذ قائمة الانتظار هي مؤشرات thread-safe
. جميع طرق الانتظار ذرية بطبيعتها وتستخدم الأقفال الداخلية.
لنبدأ في تنفيذ Thread-Safe BlockingQueue في Java
الخطوة 1
قم بإنشاء فئة CrunchifyMessage.java
. هذا هو كائن جافا بسيط.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com . crunchify . example ; /** * @author Crunchify.com * simple Message class to put and get message into queue */ public class CrunchifyMessage { private String crunchifyMsg ; public CrunchifyMessage ( String string ) { this . crunchifyMsg = string ; } public String getMsg ( ) { return crunchifyMsg ; } } |
الخطوة 2
قم بإنشاء منتج CrunchifyBlockingProducer.java
الذي أنشأ رسالة بسيطة ووضعها في قائمة الانتظار.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package com . crunchify . example ; import java . util . concurrent . BlockingQueue ; /** * @author Crunchify.com * */ public class CrunchifyBlockingProducer implements Runnable { private BlockingQueue <CrunchifyMessage> crunchQueue ; public CrunchifyBlockingProducer ( BlockingQueue <CrunchifyMessage> queue ) { this . crunchQueue = queue ; } @Override public void run ( ) { // producing CrunchifyMessage messages for ( int i = 1 ; i < = 5 ; i ++ ) { CrunchifyMessage msg = new CrunchifyMessage ( "i'm msg " + i ) ; try { Thread . sleep ( 10 ) ; crunchQueue . put ( msg ) ; System . out . println ( "CrunchifyBlockingProducer: Message - " + msg . getMsg ( ) + " produced." ) ; } catch ( Exception e ) { System . out . println ( "Exception:" + e ) ; } } // adding exit message CrunchifyMessage msg = new CrunchifyMessage ( "All done from Producer side. Produced 50 CrunchifyMessages" ) ; try { crunchQueue . put ( msg ) ; System . out . println ( "CrunchifyBlockingProducer: Exit Message - " + msg . getMsg ( ) ) ; } catch ( Exception e ) { System . out . println ( "Exception:" + e ) ; } } } |
الخطوه 3
قم بإنشاء فئة CrunchifyBlockingConsumer.java
التي تستهلك رسالة من قائمة الانتظار.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package com . crunchify . example ; import java . util . concurrent . BlockingQueue ; /** * @author Crunchify.com * */ public class CrunchifyBlockingConsumer implements Runnable { private BlockingQueue <CrunchifyMessage> queue ; public CrunchifyBlockingConsumer ( BlockingQueue <CrunchifyMessage> queue ) { this . queue = queue ; } @Override public void run ( ) { try { CrunchifyMessage msg ; // consuming messages until exit message is received while ( ( msg = queue . take ( ) ) . getMsg ( ) ! = "exit" ) { Thread . sleep ( 10 ) ; System . out . println ( "CrunchifyBlockingConsumer: Message - " + msg . getMsg ( ) + " consumed." ) ; } } catch ( InterruptedException e ) { e . printStackTrace ( ) ; } } } |
الخطوة 4
قم بإنشاء طريقة CrunchifyBlockingMain.java
البسيطة التي تدير اختبار BlockingQueue. قم بتشغيل هذا البرنامج للتحقق من سلوك BlockingQueue.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package com . crunchify . example ; import java . util . concurrent . ArrayBlockingQueue ; import java . util . concurrent . BlockingQueue ; /** * @author Crunchify.com * */ public class CrunchifyBlockingMain { public static void main ( String [ ] args ) { // Creating BlockingQueue of size 10 // BlockingQueue supports operations that wait for the queue to become non-empty when retrieving an element, and // wait for space to become available in the queue when storing an element. BlockingQueue <CrunchifyMessage> crunchQueue = new ArrayBlockingQueue < > ( 10 ) ; CrunchifyBlockingProducer crunchProducer = new CrunchifyBlockingProducer ( crunchQueue ) ; CrunchifyBlockingConsumer crunchConsumer = new CrunchifyBlockingConsumer ( crunchQueue ) ; // starting producer to produce messages in queue new Thread ( crunchProducer ) . start ( ) ; // starting consumer to consume messages from queue new Thread ( crunchConsumer ) . start ( ) ; System . out . println ( "Let's get started. Producer / Consumer Test Started.\n" ) ; } } |
لا يقبل BlockingQueue العناصر الفارغة . تطرح التطبيقات NullPointerException على محاولات إضافة أو طرح أو عرض قيمة خالية .
يتم استخدام القيمة الخالية كقيمة خفر للإشارة إلى فشل عمليات الاستقصاء .
نتيجة:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Let 's get started. Producer / Consumer Test Started. CrunchifyBlockingProducer: Message - i' m msg 1 produced . CrunchifyBlockingProducer : Message - i 'm msg 2 produced. CrunchifyBlockingConsumer: Message - i' m msg 1 consumed . CrunchifyBlockingConsumer : Message - i 'm msg 2 consumed. CrunchifyBlockingProducer: Message - i' m msg 3 produced . CrunchifyBlockingConsumer : Message - i 'm msg 3 consumed. CrunchifyBlockingProducer: Message - i' m msg 4 produced . CrunchifyBlockingConsumer : Message - i 'm msg 4 consumed. CrunchifyBlockingProducer: Message - i' m msg 5 produced . CrunchifyBlockingProducer : Exit Message - All done from Producer side . Produced 50 CrunchifyMessages CrunchifyBlockingConsumer : Message - i ' m msg 5 consumed . CrunchifyBlockingConsumer : Message - All done from Producer side . Produced 50 CrunchifyMessages consumed . |
متى يجب استخدام java.util.concurrent.BlockingQueue؟
- عندما تريد خنق نوع من الطلبات الواردة ، فيجب عليك استخدام نفس الشيء
- يمكن للمنتجين أن يتقدموا كثيرًا على المستهلكين بقائمة انتظار غير محدودة. إذا كان المستهلك لا يلحق بالمنتج ، فقد يتسبب ذلك في خطأ
OutOfMemoryError
. في مثل هذه المواقف ، قد يكون من الأفضل الإشارة إلى منتج محتمل بأن قائمة الانتظار ممتلئة ، والاستسلام سريعًا مع حدوث فشل.- بعبارة أخرى: يتم خنق المنتجين بشكل طبيعي.
- يتم استخدام حظر قائمة الانتظار عادةً في التطبيق المتزامن
- يوفر تنفيذًا صحيحًا وآمنًا
- يجب أن يكون استهلاك الذاكرة محدودًا أيضًا