JavaRush /مدونة جافا /Random-AR /مثال SynchronousQueue في Java - حل مشكلة Producer Consume...
profeg
مستوى

مثال SynchronousQueue في Java - حل مشكلة Producer Consumer

نشرت في المجموعة
مثال SynchronousQueue في Java - حل مشكلة Producer Consumer
SynchronousQueue هو نوع خاص من BlockingQueue حيث يجب على كل عملية إدراج أن تنتظر أمر الإزالة المقابل في مؤشر ترابط آخر، والعكس صحيح. عند استدعاء الأسلوب put() على SynchronousQueue، فإنه يتم حظره حتى يأخذ مؤشر ترابط آخر هذا العنصر منه. وفقًا لذلك، إذا حاول مؤشر ترابط آخر إزالة عنصر منه، ولم يكن العنصر موجودًا، فسيتم حظر هذا الخيط حتى يضع الخيط الآخر العنصر في قائمة الانتظار. يمكنك التفكير في SynchronousQueue كرياضي ( خيط ) يركض بالشعلة الأولمبية، يركض بالشعلة (الشيء الذي يتم تمريره) ويمررها إلى رياضي آخر ينتظر على الجانب الآخر. إذا انتبهت إلى الاسم، فسوف تفهم أن SynchronousQueue سمي بهذا الاسم لسبب ما، فهو ينقل البيانات بشكل متزامن إلى مؤشر ترابط آخر ؛ ينتظر حتى يلتقط شخص ما البيانات بدلاً من مجرد إدخالها والخروج (عملية غير متزامنة). إذا كنت معتادًا على CSP وAda، فأنت تعلم أن قوائم الانتظار المتزامنة تشبه اجتماع سلاسل الرسائل. إنها مناسبة تمامًا لبنيات نقل التحكم حيث يجب أن يتزامن كائن يعمل في مؤشر ترابط واحد مع كائن في مؤشر ترابط آخر من أجل تمرير بعض المعلومات أو الحدث أو المهمة إليه. في دروس البرمجة متعددة الخيوط السابقة، تعلمنا كيفية حل مشكلة المنتج والمستهلك باستخدام أساليب الانتظار والإخطار و BlockingQueue . الآن سوف نتعلم كيفية تطبيق نمط المنتج والمستهلك باستخدام SynchronousQueue. تدعم هذه الفئة أيضًا السلوك العادل لطلب فترات انتظار سلاسل المنتج والمستهلك. بشكل افتراضي، هذا الطلب غير مضمون. ومع ذلك، فإن قوائم الانتظار التي تم إنشاؤها باستخدام خصائص عادلة تضمن الوصول إلى سلاسل العمليات الموجودة في قائمة انتظار FIFO (Firs In First Out).
المنتج/المستهلك باستخدام SynchronousQueue في Java.
مثال SynchronousQueue في Java - حل مشكلة Producer Consumer - 1 كما قلت أعلاه، لا يوجد شيء أفضل من مشكلة المنتج والمستهلك لفهم التواصل بين الخيوط في أي لغة برمجة. في هذه المشكلة، يعمل أحد الخيط كمنتج ينتج الأحداث والمهام، ويعمل الخيط الآخر كمستهلك لها. يتم استخدام المخزن المؤقت المشترك لنقل البيانات من المنتج إلى المستهلك. صعوبة حل هذه المشكلة تأتي في الحالات القصوى، على سبيل المثال، عندما تضطر الشركة المصنعة إلى الانتظار بسبب... المخزن المؤقت ممتلئ أو يضطر المستهلك إلى الانتظار بسبب المخزن المؤقت فارغ. تم حل هذه المشكلة بسهولة، لأن... لم توفر قائمة انتظار الحظر مخزنًا مؤقتًا لتخزين البيانات فحسب، بل توفر أيضًا التحكم في التدفق، وحظر الخيط الذي يستدعي طريقة put() (المنتج) إذا كان المخزن المؤقت ممتلئًا، وحظر الخيط الذي يستدعي طريقة take() (المستهلك) إذا كان المخزن المؤقت كان فارغا. الآن سوف نقوم بحل هذه المشكلة نفسها باستخدام SynchronousQueue، وهو نوع خاص من المجموعات المتوازية بسعة صفر. في المثال التالي، لدينا خيطين يسمى PRODUCER و CONSUMER (قم دائمًا بإعطاء أسماء لسلاسل الرسائل، وهذا أسلوب جيد جدًا للبرمجة متعددة الخيوط)، يقوم الخيط الأول بنشر النتيجة في اللعبة، والخيط الثاني يستهلكها. النتيجة في اللعبة ليست أكثر من كائن من النوع String. لكن إذا قمت بتشغيل البرنامج بنوع مختلف فلن تلاحظ أي فرق. لفهم كيفية عمل SynchronousQueue، وكيفية حل مشكلة المنتج والمستهلك، تحتاج إلى: إما تشغيل برنامج التصحيح (تصحيح الأخطاء) في بيئة Eclipse ، أو ببساطة بدء سلسلة المنتج عن طريق التعليق على Consumer.start(); إذا كان مؤشر ترابط المستهلك لا يعمل، فسيتم حظر مؤشر ترابط المنتج في queue.put(event); في حالة التشغيل، لن تتمكن من رؤية المنتج [PRODUCER] ينشر الحدث:FOUR. يحدث هذا بسبب سلوك محدد لـ SynchronousQueue، والذي يضمن أن مؤشر الترابط الذي ينشر البيانات سيتم حظره حتى يأخذ مؤشر ترابط آخر البيانات، والعكس صحيح. يمكنك اختبار بقية الكود من خلال التعليق على Producer.start(); والبدء فقط في موضوع المستهلك. إذا قمت بدراسة ما يخرجه البرنامج بعناية، ستلاحظ أن ترتيب المخرجات قد تم عكسه. يبدو أن خيط [CONSUMER] أخذ البيانات قبل أن ينتجها خيط [PRODUCER] . وذلك لأن SynchronousQueue لا يضمن الانتظار بشكل افتراضي. ولكن لديها قواعد عدالة تحدد الوصول إلى سلاسل الرسائل بترتيب FIFO. يمكنك تمكين هذه القواعد عن طريق تمرير true إلى مُنشئ SynchronousQueue المثقل مثل هذا: import java.util.concurrent.SynchronousQueue; /** * Java Program to solve Producer Consumer problem using SynchronousQueue. A * call to put() will block until there is a corresponding thread to take() that * element. * * @author Javin Paul */ public class SynchronousQueueDemo{ public static void main(String args[]) { final SynchronousQueue queue = new SynchronousQueue (); Thread producer = new Thread("PRODUCER") { public void run() { String event = "FOUR"; try { queue.put(event); // thread will block here System.out.printf("[%s] published event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; producer.start(); // starting publisher thread Thread consumer = new Thread("CONSUMER") { public void run() { try { String event = queue.take(); // thread will block here System.out.printf("[%s] consumed event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; consumer.start(); // starting consumer thread } } Output: [CONSUMER] consumed event : FOUR [PRODUCER] published event : FOUR new SynchronousQueue(boolean fair).
ما تحتاج إلى تذكره حول SynchronousQueue في Java.

فيما يلي بعض الخصائص المهمة لهذا النوع الخاص من قائمة انتظار الحظر في Java. من المفيد جدًا تمرير البيانات من مؤشر ترابط إلى آخر بطريقة متزامنة. لا تحتوي قائمة الانتظار هذه على سعة ويتم حظرها حتى يحررها مؤشر ترابط آخر.

  1. كتل SynchronousQueue، وحتى يصبح أحد الخيوط جاهزًا لأخذ البيانات، سيحاول آخر وضع البيانات.
  2. ليس لدى SynchronousQueue وحدة تخزين. أي أنه لا يحتوي على بيانات.
  3. يتم استخدام SynchronousQueue لتنفيذ إستراتيجية قائمة الانتظار الأمامية، حيث يقوم مؤشر الترابط بتمرير التحكم إلى مؤشر ترابط انتظار، أو إنشاء مؤشر ترابط جديد إذا سمح بذلك، وإلا فلن يتم نقل التحكم.
  4. لا تسمح قائمة الانتظار هذه بالبيانات الفارغة. ستؤدي محاولة إضافة عنصر فارغ إلى ظهور NullPointerException .
  5. إذا كنت تستخدم أساليب أخرى من المجموعة (مثل يحتوي على)، فإن SynchronousQueue يتصرف مثل مجموعة فارغة.
  6. لا يمكنك استخدام طريقة النظرة الخاطفة لـ SynchronousQueue لأن العنصر موجود فقط عند محاولة إزالته؛ وأيضًا، لن تتمكن من إدراج العناصر (باستخدام أي طريقة) حتى يحاول مؤشر ترابط آخر إزالتها.
  7. لن تتمكن من استخدام المكرر لـ SynchronousQueue لأن... ليس لديها عناصر.
  8. يمكن إنشاء SynchronousQueue بقواعد عادلة حيث يتم ضمان الوصول إلى سلاسل الرسائل بترتيب FIFO.
ربما يتعلق الأمر كله بـ SynchronousQueue في Java. لقد ألقينا نظرة على بعض الميزات الخاصة لهذه المجموعة متعددة الخيوط، وتعلمنا كيفية حل مشكلة المنتج والمستهلك الكلاسيكية باستخدام SynchronousQueue في Java. بالمناسبة، تسميتها بقائمة الانتظار ليس صحيحًا تمامًا، لأن... لا يحتوي على عناصر. لن يكتمل استدعاء put () حتى يتم استدعاء سلاسل رسائل أخرى (). ومن الأصح أن نفكر فيه كمكان التقاء للخيوط، حيث يتشاركون في شيء ما. بمعنى آخر، إنها أداة مساعدة للتمرير المتزامن للكائنات في Java، وربما تكون بديلاً أكثر أمانًا لطريقة الانتظار والإخطار .
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION