هل هناك بديل محسّن لتطبيق Java CopyOnWriteArrayList وكيف يمكنني طلب تغيير مواصفات Java؟

StackOverflow https://stackoverflow.com//questions/21008033

  •  21-12-2019
  •  | 
  •  

سؤال

CopyOnWriteArrayList تقريبًا لديه السلوك الذي أريده، وإذا تمت إزالة النسخ غير الضرورية فسيكون هذا بالضبط ما أبحث عنه.على وجه الخصوص، يمكن أن تعمل تمامًا مثل ArrayList بالنسبة للإضافات التي يتم إجراؤها حتى نهاية ArrayList - أي أنه لا يوجد سبب لإنشاء نسخة جديدة في كل مرة وهو ما يعتبر إهدارًا كبيرًا.يمكنه فقط تقييد نهاية ArrayList فعليًا لالتقاط لقطة للقراء، وتحديث النهاية بعد إضافة العناصر الجديدة.

يبدو أن هذا التحسين يستحق إجراءه نظرًا لأن نوع الإضافة الأكثر شيوعًا بالنسبة للعديد من التطبيقات هو نهاية ArrayList - وهو سبب لاختيار استخدام ArrayList للبدء به.

لن يكون هناك أيضًا أي حمل إضافي نظرًا لأنه لا يمكن النسخ إلا عند الإلحاق وعلى الرغم من أنه لا يزال يتعين عليه التحقق مما إذا كانت إعادة الحجم ضرورية، فيجب على ArrayList القيام بذلك على أي حال.

  1. هل هناك أي تنفيذ بديل أو بنية بيانات لها هذا السلوك دون النسخ غير الضرورية للإضافات في النهاية (على سبيل المثال، خيط آمن ومُحسّن للسماح بالقراءات المتكررة مع كون الكتابة مجرد إضافات في نهاية القائمة)؟

  2. كيف يمكنني إرسال طلب تغيير لطلب تغيير مواصفات Java لإزالة نسخ الإضافات إلى نهاية CopyOnWriteArrayList (ما لم تكن إعادة الحجم ضرورية)؟

أود حقًا أن أرى هذا يتغير مع مكتبات Java الأساسية بدلاً من الحفاظ على التعليمات البرمجية المخصصة الخاصة بي واستخدامها.

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

المحلول

للإجابة على أسئلتك:

  1. أنا لست على علم بتنفيذ بديل هو قائمة وظيفية بالكامل.

  2. إذا كانت فكرتك قابلة للحياة حقا، يمكنني التفكير في عدد من الطرق للمتابعة:

    • يمكنك إرسال "طلبات التحسين" (RFE) من خلال قاعدة بيانات Gava Bugs. ومع ذلك، في هذه الحالة أشك في أنك ستحصل على استجابة إيجابية. (بالتأكيد، وليس في الوقت المناسب!)

    • يمكنك إنشاء مشكلة RFE على Guava أو مشكلات Apache Commons Tracker. قد يكون هذا أكثر مثمرة، على الرغم من أنه يعتمد على إقناعهم ...

    • يمكنك إرسال رقعة إلى فريق OpenJDK مع تنفيذ من فكرتك. لا أستطيع أن أقول ما قد تكون النتيجة ...

    • يمكنك إرسال تصحيح (على النحو الوارد أعلاه) إلى Guava أو Apache Commons عبر Triment States Trackers. هذا هو النهج الأكثر عرضة للنجاح، على الرغم من أنه لا يزال يعتمد على إقناع "لهم" بأنه صادق تقنيا، و "شيء جيد".

    • يمكنك فقط وضع التعليمات البرمجية لتنفيذه البديل المقترح على جيثب، ونرى ما يحدث.


  3. ومع ذلك، فإن كل هذا يفترض أن فكرتك ستعمل بالفعل. بناء على المعلومات الضئيلة التي قدمتها، أنا مشكوك فيها. أظن أن هناك قد تكون مشكلات مع التغليف غير المكتملة والتزامن و / أو عدم تنفيذ التجريد القائمة بالكامل / بشكل صحيح.

    أقترح عليك وضع التعليمات البرمجية الخاصة بك على جيثب بحيث يمكن لأشخاص آخرين أن يأخذوا نظرة سعيدة جيدة.

نصائح أخرى

يبدو أنك تبحث عن أ BlockingDeque, ، وعلى وجه الخصوص أ ArrayBlockingQueue.

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

تخميني هو أن السبب وراء عدم حصول القوائم على قدر كبير من الحب java.util.concurrent هو أن القائمة عبارة عن بنية بيانات مفعم بالحيوية بطبيعتها في معظم حالات الاستخدام (التكرارات الأخرى).على سبيل المثال، شيء من هذا القبيل if (!list.isEmpty()) { return list.get(0); } مفعم بالحيوية ما لم يكن محاطًا بـ synchronized block، وفي هذه الحالة لا تحتاج إلى بنية آمنة للخيوط بطبيعتها.ما تحتاجه حقًا هو واجهة "من نوع القائمة" التي تسمح فقط بالعمليات في النهايات - وهذا هو بالضبط ما تحتاجه Queue و Deque نكون.

لا يوجد سبب لتقديم نسخة جديدة في الواقع كل مرة تضيعها.

هذه هي الطريقة التي يعمل بها. يعمل بواسطة استبدال الصفيف السابق مع صفيف جديد جديد في إجراء مقارنة وتبادل. إنه جزء أساسي من تصميم سلامة الخيط لديك دائما مجموعة جديدة حتى لو كان كل ما تفعله هو استبدال إدخال.

آمنة للخيط والمحسنة للسماح للقراءة المتكررة بالكتب فقط الإضافات في نهاية القائمة

يتم تحسين ذلك بشكل كبير من القراءات، أي حل آخر سيكون أسرع للكتابة، ولكن أبطأ للقراءة وعليك أن تقرر أي منها تريد حقا.

يمكنك الحصول على بنية بيانات مخصصة والتي ستكون أفضل ما في العالمين، لكنه لم يعد هناك حل عام وهو ما يوفره ثنائي التونسونات.

كيف يمكنني تقديم طلب تغيير لطلب تغييرا إلى مواصفات Java لإزالة النسخ للإضافات إلى نهاية CopyonWriteArraylist (ما لم يكن ذلك ضروريا)؟

يمكنك القيام بذلك من خلال قاعدة بيانات الأخطاء، ولكن ما تقترحه هو تغيير أساسي في كيفية عمل بنية البيانات. أقترح اقتراح بنية بيانات جديدة / مختلفة تعمل بالطريقة التي تريدها. في الوقت نفسه أقترح تطبيقه بنفسك كمثال عمل كما ستحصل على تريد أن تريد أسرع.

أود أن أبدأ ب AtomicreferEcarray لأنه يمكن استخدام ذلك لأداء الإجراءات المنخفضة المستوى الذي تحتاجه. المشكلة الوحيدة الموجودة فيها هي أنها غير قابلة للتغيير حتى تحتاج إلى تحديد الحد الأقصى للحجم الذي ستستخدمه كل حاجة.

يحتوي copyonwritearraylist على عيب الأداء لأنه ينشئ نسخة من الصفيف الأساسي من القائمة في عمليات الكتابة. نسخ الصفيف يجعل عمليات الكتابة بطيئة. قد تكون، CopyonWriteArrayList مفيد للاستخدام لقائمة بمعدل قراءة عالية ومعدل الكتابة المنخفض.

في النهاية بدأت ترميز تطبيقي الخاص باستخدام Java.util.concurrent.locks، ReadWritelock. قمت بتنفيذي ببساطة عن طريق الحفاظ على مثيل ReadWritelock على مستوى الكائن، واكتساب قفل القراءة في عمليات القراءة واكتساب قفل الكتابة في عمليات الكتابة. الرمز يشبه هذا.

giveacodicetagpre.

تحسين الأداء لوحظ كان ملحوظا.

إجمالي الوقت المستغرق لمدة 5000 قراءة + 5000 كتابة (نسبة القراءة 1: 1) من 10 مواضيع كانت

  • arraylist - 16450 ns (غير آمنة الموضوع)
  • concurrentlist - 20999 NS
  • vector -35696 ns
  • copyonwritearraylist - 197032 ns

يرجى اتباع هذا الرابط لمزيد من المعلومات حول حالة الاختبار المستخدمة للحصول على النتائج أعلاه

ومع ذلك، من أجل تجنب concurrentmodificationsException عند استخدام جهاز الكمبيوتر، فقد أنشأت للتو نسخة من القائمة الحالية وأعادت معكر هذا. هذا يعني أن هذه القائمة لا تعود ومقاومة للماء والتي يمكنها تعديل القائمة الأصلية. حسنا، بالنسبة لي، هذا هو O.k. في الوقت الراهن.

giveacodicetagpre.

بعد بعض googling اكتشفت أن copyonwritearraylist يحتوي على مفهوم مماثل، لأنه لا يرجع اختبار للماء يمكن تعديل القائمة الأصلية. يقول جافادوك،

يوفر جهاز iTerator المرتجع لقطة لحالة القائمة عند إنشاء جهاز الكمبيوتر. هناك حاجة إلى مزامنة أثناء عبور جهاز الكمبيوتر. لا يدعم المؤتمر طريقة إزالة الإزالة.

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