2012-11-22 31 views
10

Tôi nhận được kết quả mà tôi không thực sự hiểu được khi sử dụng Bộ nhớ cache ổi.Làm sạch bộ nhớ đệm bằng tiếng tămSau khi ghi đè sự nhầm lẫn

Tôi đang triển khai bộ nhớ cache khóa duy nhất mà tôi muốn làm mới không đồng bộ.

Tôi nhấn bộ nhớ cache mỗi giây và tôi đã đặt refreshAfterWrite thành 20 giây. Chức năng tải/tải lại của tôi mất 5 giây.

Nếu tôi in ra vào lúc bắt đầu của phương pháp tải/tải lại thời gian hiện tại - Tôi mong chờ một số kết quả như thế này:

gọi tải bắt đầu lúc 00:00:00
gọi tải lại bắt đầu lúc 00:00:25
gọi tải lại bắt đầu lúc 00:00:50

Vì vậy, các tải sẽ mất 5 giây và ghi tiếp theo sẽ kích hoạt 20 giây sau đó (5 + 20 = 25). ghi có thể xảy ra ở 50 giây (25 + 5 + 20 = 50) giây sau đó .. vv

Thay vào đó tôi nhận được:

gọi tải bắt đầu lúc 00:00:00
gọi tải lại bắt đầu tại 00:00:25
gọi tải lại bắt đầu lúc 00:00:30

Điều này cho thấy reload thứ hai xảy ra ngay sau khi reload đầu tiên đã xử lý xong.

Tôi nghĩ rằng việc viết sẽ xảy ra sau khi tương lai đã được xử lý và do đó việc tải lại tiếp theo sẽ được lên lịch trong 20 giây sau đó?

Tôi đã tìm thấy lỗi hay tôi có một sự hiểu lầm cơ bản về cách refreshAfterWrite hoạt động?

Mẫu mã là dưới đây:

private static SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss"); 

    public static void main(String[] args) throws ExecutionException, InterruptedException { 

     final ExecutorService executor = Executors.newFixedThreadPool(3); 

     final LoadingCache<String, Long> cache = CacheBuilder.newBuilder().maximumSize(1) // 
       .refreshAfterWrite(20, TimeUnit.SECONDS)// 
       .build(new CacheLoader<String, Long>() {// 
        public Long load(String key) { 
         return getLongRunningProcess("load", key); 
        } 

        public ListenableFuture<Long> reload(final String key, Long prevGraph) { 
         ListenableFutureTask<Long> task = ListenableFutureTask.create(new Callable<Long>() { 
          public Long call() { 
           return getLongRunningProcess("reload", key); 
          } 
         }); 
         executor.execute(task); 
         return task; 
        } 
       }); 

     while (true) { 
      Thread.sleep(1000L); 
      cache.get(CACHE_KEY); 
     } 
    } 

    private static Long getLongRunningProcess(String callType, String key) { 
     System.out.printf("%s call started at %s\n", callType, format.format(new Date())); 
     try { 
      Thread.sleep(5000L); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     return counter.getAndIncrement(); 
    } 

} 
+0

Vài tuần trước, tôi đang tìm kiếm một tính năng yếu tố bộ nhớ cache đơn đáng quên. Đáng buồn thay, điều này không được hỗ trợ trong ổi nhưng vì vậy tôi đã viết một bản thân mình. Hãy xem nỗ lực của tôi để thực hiện điều này tại http://codereview.stackexchange.com/questions/18056/ability-to-forget-the-memoized-supplier-value và vui lòng sử dụng mã này nếu bạn cần. – mindas

Trả lời

7

tôi nghĩ bạn đã tìm thấy một lỗi legit. (. Tôi giúp duy trì common.cache)

Nếu tôi sau những điều đúng, tôi tin rằng các chuỗi sự kiện như sau:

Hãy nói rằng có được A là get đầu tiên gây ra một làm mới, và nhận được B là get đầu tiên sau đó.

  • Nhận cuộc gọi scheduleRefresh, bắt đầu nhiệm vụ refresh trong người thi hành. Tham chiếu giá trị mục nhập được thay thế bằng một số LoadingValueReferenceloadAsync thêm người nghe chờ đợi quá trình tải lại hoàn tất.
  • Nhiệm vụ được chia đôi cho việc tải lại Get A hoàn tất và mua lại khóa.
  • Nhận cuộc gọi B scheduleRefresh. Thời gian truy cập chưa được cập nhật, do đó, thời gian truy cập vẫn tiếp tục và đi vào insertLoadingValueReference.
  • Nhiệm vụ được chia đôi cho Tải lại Get A cập nhật thời gian ghi và thay thế tham chiếu giá trị bằng StrongValueReference, vì quá trình tải hoàn tất. Khóa được giải phóng.
  • Nhận B xác định rằng giá trị không còn trong quá trình tải, do đó, nó bắt đầu để bắt đầu tải lại mới.

(Cập nhật: nộp https://code.google.com/p/guava-libraries/issues/detail?id=1211.)

+0

Cảm ơn bạn đã trả lời! Sự hiểu biết cơ bản của tôi có đúng về hành vi đúng đắn không? Tức là, nếu bộ nhớ cache nhận yêu cầu ở khoảng thời gian thông thường nhỏ hơn thời gian cần thiết để làm mới lại thì chúng ta có thể giả định rằng làm mới sẽ bắt đầu vào khoảng thời gian cố định tương ứng với: (thời gian cần để thực hiện làm mới) + (khoảng thời gian làm mới)? - Không phải là tôi sẽ căn cứ vào bất kỳ giải pháp nào về điều này, vì việc lên kế hoạch làm mới định kỳ sẽ sạch hơn! – plasma147

+0

Điều đó phù hợp với việc đọc thông số của tôi, vâng. –

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