سؤال

لقد استخدمت LinkedHashMap مع accessOrder صحيح مع السماح بحد أقصى 500 إدخال في أي وقت كذاكرة تخزين مؤقت LRU للبيانات.ولكن بسبب مشكلات قابلية التوسع، أرغب في الانتقال إلى بديل آمن لسلسلة الرسائل. ConcurrentHashMap يبدو جيدًا في هذا الصدد، لكنه يفتقر إلى ميزات accessOrder و removeEldestEntry(Map.Entry e) عثر عليه في LinkedHashMap.هل يمكن لأي شخص أن يشير إلى رابط ما أو يساعدني في تسهيل التنفيذ.

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

المحلول

لقد فعلت شيئًا مشابهًا مؤخرًا مع ConcurrentHashMap<String,CacheEntry>, ، حيث يقوم CacheEntry بتغليف العنصر الفعلي وإضافة إحصائيات إزالة ذاكرة التخزين المؤقت:وقت انتهاء الصلاحية، ووقت الإدراج (لإخلاء FIFO/LIFO)، وآخر وقت استخدام (لإخلاء LRU/MRU)، وعدد الزيارات (لإخلاء LFU/MFU)، وما إلى ذلك.تتم مزامنة الإخلاء الفعلي وإنشاء ArrayList<CacheEntry> ويقوم بإجراء Collections.sort() عليه باستخدام المقارنة المناسبة لاستراتيجية الإخلاء.نظرًا لأن هذا مكلف، فإن كل عملية إخلاء تقطع نسبة الـ 5% السفلية من CacheEntries.أنا متأكد من أن ضبط الأداء سيساعد بالرغم من ذلك.

في حالتك، نظرًا لأنك تقوم بتنفيذ ما يصرف أولاً، يمكنك الاحتفاظ بملف منفصل قائمة الانتظار المتزامنة.عند إضافة كائن إلى ConcurrentHashMap، قم بإجراء ConcurrentLinkedQueue.add() لذلك الكائن.عندما تريد حذف إدخال، قم بإجراء ConcurrentLinkedQueue.poll() لإزالة الكائن الأقدم، ثم قم بإزالته من ConcurrentHashMap أيضًا.

تحديث:تشمل الإمكانيات الأخرى في هذا المجال مجموعات Java غلاف المزامنة وجافا 1.6 ConcurrentSkipListMap.

نصائح أخرى

هل حاولت استخدام واحدة من العديد من الحلول التخزين المؤقت مثل ehcache؟ هل يمكن أن حاول استخدام LinkedHashMap مع ReadWriteLock. هذا من شأنه أن يوفر لك الوصول للقراءة المتزامنة.

وهذا قد يبدو من العمر الآن، ولكن على الأقل لمجرد بلدي تتبع تاريخنا، وانا ذاهب لإضافة لي الحل هنا: I جنبا إلى جنب ConcurrentHashMap التي تعين K-> فئة فرعية من WeakReference، ConcurrentLinkedQueue، وواجهة التي تعرف إلغاء التسلسل من الكائنات قيمة تستند K لتشغيل LRU التخزين المؤقت بشكل صحيح. قائمة الانتظار يحمل الحكام قوي، وسوف GC طرد القيم من الذاكرة عند الاقتضاء. تتبع حجم قائمة انتظار المشاركة AtomicInteger، كما لا يمكن أن تفقد حقا قائمة الانتظار لتحديد متى يتم طرد. سوف ذاكرة التخزين المؤقت التعامل مع الطرد من / إضافة إلى قائمة الانتظار، فضلا عن إدارة خريطة. إذا كان GC طرد القيمة من الذاكرة، وتنفيذ واجهة إلغاء التسلسل التعامل مع استرجاع القيمة مرة أخرى. كان لي أيضا تنفيذ آخر أن تشارك التخزين المؤقت على القرص / إعادة قراءة ما تم تخزينه، لكن ذلك كان أبطأ بكثير من حل نشرت لي هنا، وإيهاب لمزامنة التخزين المؤقت / القراءة.

وأذكر لكم الرغبة في حل المشاكل التدرجية مع بديل "ذات ألوان". "سلامة الموضوع" هنا يعني أن الهيكل هو تسامحا من محاولات الوصول المتزامن، حيث أنه لن تعاني الفساد الاستخدام المتزامن دون تزامن الخارجي. ومع ذلك، فإن مثل هذا التسامح لا يساعد بالضرورة إلى تحسين "قابلية". في أبسط - على الرغم من عادة المضلل - النهج، عليك محاولة مزامنة الهيكل الخاص داخليا ولا تزال تترك غير الذري <م> الاختيار آنذاك فعل عمليات غير آمنة

. تتطلب

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

والجواب المقبول حاليا تذكر "عندما تريد طرد إدخال". هنا يكمن فرك. كيف يمكنك أن تعرف عندما تريد طرد إدخال؟ التي عمليات أخرى لا تحتاج إلى وقفة من أجل اتخاذ هذا القرار؟

والتفاف الخريطة في Collections.synchronizedMap(). إذا كنت بحاجة إلى استدعاء الأساليب إضافية، ثم synchronize على الخريطة التي حصلت على العودة من هذه الدعوة، واستدعاء الأسلوب الأصلي على الخريطة الأصلية (<لأ href = "http://java.sun.com/j2se/1.5. 0 / مستندات / المعهد / جافا / UTIL / Collections.html # synchronizedMap٪ 28java.util.Map٪ 29 "يختلط =" نوفولو noreferrer "> رؤية javadocs للحصول على مثال ). وينطبق الشيء نفسه عند تكرار عبر المفاتيح، الخ.

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