8

Java Gurus,ConcurrentHashMap vs ReentrantReadWriteLock Bản đồ tùy chỉnh dựa cho Reloading

Hiện nay chúng tôi có một HashMap<String,SomeApplicationObject> mà đang được đọc thường xuyên và sửa đổi thường xuyên và chúng tôi đang gặp vấn đề rằng trong/tải lại, đọc lợi nhuận hoạt động sửa đổi null không được chấp nhận.

Để sửa lỗi này tôi có các tùy chọn sau đây:

A. Sử dụng ConcurrentHashMap

nào trông giống như lựa chọn đầu tiên nhưng các hoạt động mà chúng ta đang nói về là reload() - có nghĩa là clear() Tiếp theo replaceAll(). Vì vậy, nếu các Map được đọc bài clear() và trước replaceAll() nó trả về null mà không phải là mong muốn. Ngay cả khi tôi synchronize điều này không giải quyết được vấn đề.

B. Tạo một thực hiện dựa trên ReentrantReadWriteLock

đâu tôi sẽ tạo ra Acquire Write Lock trước reload() hoạt động. Điều này có vẻ phù hợp hơn nhưng tôi cảm thấy phải có một cái gì đó đã có sẵn cho điều này và tôi không cần phải tái tạo lại bánh xe.

Cách tốt nhất là gì?

EDIT Có bất kỳ Bộ sưu tập nào đã có sẵn với tính năng này không?

+0

Bản đồ của bạn có hiệu quả bất biến, làm cho chúng trở thành mục tiêu hoàn hảo để xuất bản qua 'biến động '. –

+0

** Không thay đổi có hiệu quả ** xin lỗi tôi không hiểu 'không thể thay đổi' mà tốt ... Bạn có thể vui lòng cung cấp một số gợi ý ??? – SiB

Trả lời

4

Có vẻ như bạn không chắc chắn về những gì Peter Lawrey gợi ý có thể được thực hiện. Nó có thể trông như thế này:

class YourClass { 
    private volatile Map<String, SomeApplicationObject> map; 

    //constructors etc. 

    public void reload() { 
     Map<String,SomeApplicationObject> newMap = getNewValues(); 
     map = Collections.unmodifiableMap(newMap); 
    } 
} 

Không có vấn đề đồng thời bởi vì:

  • Các bản đồ mới được tạo ra thông qua một biến địa phương, mà theo định nghĩa không được chia sẻ - getNewValues không cần phải được đồng bộ hoặc nguyên tử
  • các assignement để map là nguyên tử
  • map là không ổn định, trong đó đảm bảo rằng chủ đề khác sẽ thấy sự thay đổi
8

Vì bạn đang tải lại bản đồ, tôi sẽ thay thế bản đồ đó khi tải lại.

Bạn có thể thực hiện việc này bằng cách sử dụng Bản đồ dễ bay hơi mà bạn thay thế đầy đủ khi được cập nhật.

+0

bạn có thể giải thích chi tiết hơn không? Đó là bằng cách nào đó khó khăn cho tôi để lý do tại sao điều này sẽ làm việc. Tôi hiểu rằng dễ bay hơi sẽ đảm bảo khả năng hiển thị, nhưng làm thế nào một hoạt động hợp chất như rõ ràng hơn replaceAll sẽ làm việc? Cảm ơn bạn. – Eugene

+0

Để thay thế toàn bộ bản đồ, tất cả những gì bạn phải làm là gán bản đồ mới cho tham chiếu biến động cũ trong trường của bạn khi bạn đã tạo bản sao mới. tức là bạn thực sự đang thay thế tất cả, ngay cả bản thân bản đồ không chỉ là nội dung của nó. –

5

Điều này nghe có vẻ là như Guava'sCache, mặc dù nó thực sự phụ thuộc vào cách bạn đang điền bản đồ và cách bạn tính giá trị. (Tiết lộ: Tôi đóng góp cho Guava.)

Câu hỏi thực sự là liệu bạn có thể chỉ định cách tính số SomeApplicationObject của mình cho đầu vào String hay không. Chỉ cần dựa trên những gì bạn đã nói với chúng tôi cho đến nay, nó có thể giống như thế này ...

LoadingCache<String, SomeApplicationObject> cache = CacheBuilder.newBuilder() 
    .build(
     new CacheLoader<String, SomeApplicationObject>() { 
     public SomeApplicationObject load(String key) throws AnyException { 
      return computeSomeApplicationObject(key); 
     } 
     }); 

Sau đó, bất cứ khi nào bạn muốn xây dựng lại bộ nhớ cache, bạn chỉ cần gọi cache.invalidateAll(). Với số LoadingCache, bạn có thể gọi cache.get(key) và nếu nó chưa tính giá trị, nó sẽ được tính lại. Hoặc có thể sau khi gọi số cache.invalidateAll(), bạn có thể gọi cache.loadAll(allKeys), mặc dù bạn vẫn cần có thể tải từng phần tử trong trường hợp có bất kỳ truy vấn nào nằm giữa các số invalidateAllloadAll.

Nếu điều này không được chấp nhận - nếu bạn không thể tải một giá trị riêng lẻ, bạn phải tải tất cả cùng một lúc - sau đó tôi tiếp tục với cách tiếp cận của Peter Lawrey - giữ tham chiếu volatile bản đồ (lý tưởng là ImmutableMap), tính lại toàn bộ bản đồ và gán bản đồ mới cho tham chiếu khi bạn hoàn tất.

+0

SomeApplicationObject là một thực thể được tải sẵn từ DB khi ứng dụng bắt đầu và đọc từ Bản đồ mọi lúc ... Đôi khi, Quản trị viên hệ thống có thể tải lại các giá trị. – SiB

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