هل كانت مفيدة؟

المحلول

لموضوع منتج / المستهلك، وأنا لست متأكدا من أن ConcurrentLinkedQueue، بل هو خيار معقول - لا تنفيذ BlockingQueue، الذي هو واجهة أساسية لطوابير منتج / المستهلك IMO. كنت قد لاستدعاء poll()، انتظر قليلا إذا كنت لم أعثر على أي شيء، ثم مرة أخرى استطلاع الخ ... مما يؤدي إلى التأخير عندما يأتي بند جديد في، وعدم الكفاءة عندما يكون فارغا (بسبب الاستيقاظ من النوم دون داع من ينام ).

ومن مستندات لBlockingQueue:

<اقتباس فقرة>   صممت

وتطبيقات BlockingQueue لاستخدامها في المقام الأول لصفوف المنتجين والمستهلكين

وأنا أعلم أنه لا <م> بدقة القول بأن طوابير فقط عرقلة يجب أن تستخدم لطوابير المنتجين والمستهلكين، ولكن على الرغم من ذلك ...

نصائح أخرى

وهذا السؤال يستحق الجواب الأفضل.

ويستند ConcurrentLinkedQueue جاوة على خوارزمية الشهيرة التي كتبها ماجد M. مايكل ومايكل L. سكوت للحصول على عدم عرقلة طوابير خالية من القفل.

و"عدم عرقلة" كمصطلح هنا للحصول على الموارد ادعت (لدينا طابور) يعني أنه بغض النظر عن ما تفعله جدولة للمنبر، مثل انقطاع الخيط، أو إذا كان موضوع في السؤال هو ببساطة بطيئة جدا، المواضيع الأخرى معتبرا ل فإن نفس المصدر لا يزال قادرا على التقدم. إذا كان الأمر ينطوي على قفل على سبيل المثال، موضوع عقد التأمين يمكن أن توقف وسيتم حظر كافة المواضيع انتظار أن القفل. أقفال الجوهرية (الكلمة synchronized) في جافا ويمكن أيضا أن تأتي مع عقوبة قاسية لأداء - مثل عندما <لأ href = "http://www.oracle.com/technetwork/java/6-performance-137236.html#2.1. 1 "> منحازة قفل هو المشاركة ولديك خلاف، أو بعد يقرر VM ب" تضخيم "القفل بعد فترة تدور النعمة وكتلة معتبرا المواضيع ... وهذا هو السبب في العديد من السياقات (سيناريوهات منخفضة / خلاف المتوسط)، والقيام مقارنة ومجموعات على المراجع الذرية يمكن أن تكون أكثر فاعلية وهذا هو بالضبط ما عديدة غير مؤمن هياكل البيانات تقوم به.

وConcurrentLinkedQueue جافا ليست غير مؤمن فقط، ولكنها تحتوي على خاصية رهيبة أن المنتج لا يتعامل مع المستهلك. في منتج واحد / السيناريو المستهلك واحد (SPSC)، وهذا يعني في الواقع أنه لن يكون هناك أي خلاف يمكن الحديث عنها. في سيناريو المستهلك منتج متعددة / وحيد، فإن المستهلك لا يتعامل مع المنتجين. قائمة الانتظار هذه لديها خلاف عندما يحاول المنتجون متعددة لoffer()، ولكن هذا التوافق من حيث التعريف. انها في الاساس للأغراض العامة وكفاءة طابور غير مؤمن.

وأما عن أنه لم يكن لBlockingQueue، حسنا، وعرقلة الموضوع إلى الانتظار في طابور هو وسيلة رهيبة فظيع من تصميم نظم المتزامنة. لا. إذا لم تتمكن من معرفة كيفية استخدام ConcurrentLinkedQueue في سيناريو المستهلك / المنتج، ثم مجرد تحول إلى تجريدات على مستوى أعلى، مثل إطار ممثل جيد.

وكتل LinkedBlockingQueue المستهلك أو المنتج عند قائمة الانتظار فارغ أو الكامل ويتم وضع موضوع المستهلك / المنتج منها إلى النوم. ولكن هذه الميزة حجب يأتي مع التكلفة: كل وضع أو اتخاذ تشغيل وقفل ادعت بين المنتجين أو المستهلكين (إذا كان كثير)، وذلك في سيناريوهات مع العديد من المنتجين / المستهلكين العملية قد يكون أبطأ

وConcurrentLinkedQueue لا يستخدم الأقفال، ولكن CAS ، على وضع لها / اتخاذ عمليات خفض محتمل خلاف مع العديد من المواضيع المنتج والمستهلك. ولكن كونه "الانتظار الحر" هيكل البيانات، وConcurrentLinkedQueue لن تعرقل عندما تكون فارغة، وهذا يعني أن المستهلك سوف تحتاج إلى التعامل مع take() بإرجاع قيم null من قبل "الانتظار مشغول"، على سبيل المثال، مع موضوع المستهلكين تلتهم وحدة المعالجة المركزية.

وحتى واحد الذي هو "أفضل" يعتمد على عدد من المواضيع المستهلك، وعلى سعر أنها تستهلك / إنتاج، الخ وهناك حاجة إلى مرجعية لكل سيناريو.

واحد حالة استخدام معينة حيث ConcurrentLinkedQueue هو أفضل بوضوح هو عندما المنتجين لأول مرة تنتج شيئا والانتهاء من عملهم من خلال وضع العمل في قائمة الانتظار و فقط بعد كما المستهلكين يبدأ تستهلك، مع العلم أنها سوف القيام به عندما طابور فارغ. (هنا ليس التزامن بين المنتجين والمستهلكين ولكن فقط بين المنتج منتج ومستهلك للمستهلك)

وهناك حل آخر (لا مقياس جيد) هي قنوات التقاء: java.util.concurrent SynchronousQueue

إذا قائمة الانتظار هو غير قابلة للتوسيع ويحتوي فقط على منتج واحد / موضوع المستهلك. يمكنك استخدام طابور lockless (لا تحتاج لتأمين الوصول إلى البيانات).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top