2012-05-04 35 views
7

Trong Thư viện ổi, tôi nhầm lẫn về lý do tại sao Cache.asMap() không nhất quán với Cache.size(), trừ khi Cache.cleanUp() được gọi.Tại sao Cache.asMap() không phù hợp với Cache.size()?

Cache<Object, Object> cache = CacheBuilder.newBuilder() 
      .expireAfterWrite(1, TimeUnit.SECONDS) 
      .build(); 
cache.get(...); 
... 
//After some seconds, all entries are expired. 
//cache.asMap() is EMPTY Map, but cache.size() != 0 

Vì vậy, câu hỏi của tôi: Có lỗi Cache.asMap() là không phù hợp để Cache.size()? Mặc dù tôi nhận thấy sự javadoc của Cache.size() là:

/** 
    * Returns the **approximate** number of entries in this cache. 
    */ 

Tôi chỉ có thể đoán nó liên quan đến một môi trường đồng thời. Và những gì hiện Cache.cleanUp() làm chính xác?

Trả lời

13

Bộ nhớ cache của ổi được thiết kế xung quanh khấu hao khóa và phương pháp cleanUp buộc bộ nhớ cache đến trạng thái nhất quán. Phương pháp Map.size() là một phép tính xấp xỉ, nhưng có thể đếm các mục đang chờ xóa do hết hạn hoặc việc loại bỏ tham chiếu. Khả năng hiển thị của các xấp xỉ trong bộ nhớ cache của ổi hiếm khi có nhiều sự quan tâm đến một ứng dụng, mà có xu hướng nghĩ về một bộ nhớ đệm như một kho lưu trữ dữ liệu tạm thời. Những kỳ vọng khác nhau của bộ nhớ cache từ Bản đồ dẫn đến phương pháp asMap để cho phép bộ nhớ cache được xem dưới dạng bản đồ, nhưng không ưa thích các nhà phát triển cảm nhận nó theo cách đó.

Chi tiết triển khai bộ nhớ cache được đề cập trong hội nghị StrangleLoop 2011 slides. Các design document của ConcurrentLinkedHashMap, bộ nhớ đệm của Guava có nguồn gốc từ, cũng có thể được quan tâm nhưng mô tả một cách tiếp cận hơi khác nhau.

9

Ben đưa ra phản hồi mức cao tốt. Câu trả lời cấp thấp là:

asMap() lượt xem có tính năng vượt qua ngang qua từng phần tử trong bộ nhớ cache và do đó có thể bỏ qua các mục không hợp lệ đang chờ xử lý. Mặt khác, size() dự kiến ​​sẽ hoạt động nhanh và sẽ rất ngớ ngẩn khi duyệt toàn bộ bộ nhớ cache chỉ để có được ước tính kích thước chính xác hơn.

CacheBuilder javadocs đi vào chi tiết hơn về việc dọn dẹp cần phải xảy ra trong các tình huống khác nhau (chẳng hạn như expireAfterWrite, trong trường hợp của bạn).

+1

Cảm ơn bạn, Charles! Tôi đã đi qua mã nguồn gần, 'size()' chỉ tính tổng của Segment, như bạn đã đề cập- "ngớ ngẩn để đi qua toàn bộ bộ nhớ cache chỉ để có được một ước tính kích thước chính xác hơn" :) Thiết kế tinh vi! –

Các vấn đề liên quan