2010-02-12 9 views
9

Trước đây tôi đi đến kết luận rằng nếu bạn cần một SoftReference với giá trị bằng (equals) dựa trên bình đẳng thì có một thiết kế xấu, ngoại trừ một interner từ này. Theo dõi Bộ sưu tập của Google và Guava không bao gồm một lớp học như vậy. Nhưng tôi đã đi qua một vấn đề mà tôi nghĩ rằng có thể sử dụng một đối tượng như vậy.Sử dụng tiềm năng cho SoftReference với giá trị (bằng) bình đẳng

Chúng tôi có một hệ thống quản lý tài sản trong một hiệu ứng hình ảnh kết xuất trang trại với 100 quy trình chạy cùng một công việc chỉ khác nhau về số khung mà nó hiển thị. Chúng tôi có một cơ sở dữ liệu Oracle cần ghi lại tất cả các tài sản được sử dụng. Thay vì đập Oracle với chèn giống hệt nhau, nơi chỉ có một sẽ thành công từ tất cả các công việc, trong hệ thống quản lý tài sản tầng giữa chúng ta có thể sử dụng một HashSet để ghi lại nếu đối tượng sẽ được chèn vào Oracle.

Tôi có thể sử dụng Google MapMaker với thời gian hết hạn, nhưng tôi không muốn phải lo lắng về việc hết hạn chính xác, chúng tôi có hiển thị chạy hàng giờ và vài ngày qua. Sử dụng SoftReference với âm thanh bình đẳng như một cách tốt hơn nhiều để JVM sẽ tự động quản lý việc thu gom rác. Đối với các vấn đề khác mà tôi muốn giải quyết bằng ConcurrentHashMap với bộ sưu tập rác, tôi sẽ sử dụng tham chiếu mạnh mẽ trong HashMap làm khóa để lấy equals() equality và SoftReference làm giá trị để JVM có thể thu thập thứ gì đó , nhưng trong trường hợp này, giá trị không quan trọng và tôi không có giá trị để bọc trong SoftReference để đặt ở đó. Vì vậy, nó có vẻ như sử dụng một SoftReference với bằng() sẽ làm các trick.

Bất kỳ đề xuất nào khác về điều này?

+1

Yêu câu hỏi của bạn, tôi đã tự hỏi về điều đó cũng gần đây – nanda

+0

Không 'ResourceBundle' làm điều gì đó như thế này? –

+0

@nanda những gì được thêm vào Oracle là một danh sách các tài sản (nói tên tập tin trên một máy chủ NFS) được tạo động; ResourceBundle có vẻ không phù hợp. Tôi chỉ cần một HashSet để ghi lại rằng tên tập tin đã được ghi lại trong Oracle do đó, 99 lần thử chèn nó không lãng phí các chu kỳ CPU trong Oracle. –

Trả lời

1

Trong hầu hết các trường hợp khi bạn muốn sử dụng tài liệu tham khảo mềm với Google Collections, bạn nên gọi

MapMaker.softValues() 

Với phím mạnh mẽ nhưng giá trị mềm, tra cứu sẽ sử dụng bình đẳng và giá trị khóa cặp sẽ được thu gom rác thải khi bộ nhớ Là chặt chẽ.

+0

Nhưng tôi không có giá trị để liên kết với khóa, do đó, chìa khóa là điều duy nhất có thể được đặt trong một tham chiếu mềm. –

0

Tôi nghĩ rằng lớp này sẽ đáp ứng nhu cầu của bạn:

import java.util.*; 
import java.lang.ref.*; 

public class SoftSet<T> extends AbstractSet<T> { 

    private final WeakHashMap<T,SoftReference<T>> data = new WeakHashMap<T,SoftReference<T>>(); 

    public boolean add(T t) { 
    return null == data.put(t, new SoftReference<T>(t)); 
    } 

    public boolean remove(Object o) { 
    return null != data.remove(o); 
    } 

    public boolean contains(Object o) { 
    return data.containsKey(o); 
    } 

    public Iterator<T> iterator() { 
    return data.keySet().iterator(); 
    } 

    public int size() { 
    return data.size(); 
    } 

    public void clear() { 
    data.clear(); 
    } 

    public boolean removeAll(Collection<?> c) { 
    return data.keySet().removeAll(c); 
    } 

    public boolean retainAll(Collection<?> c) { 
    return data.keySet().retainAll(c); 
    } 
} 

Cách mà nên làm việc này là một khi các tài liệu tham khảo mềm đó là giá trị sẽ bị xóa, sau đó giá trị là yếu thể truy cập chỉ và chìa khóa có thể được loại bỏ khỏi bản đồ bên trong.

+0

Có lẽ downvote vì nó gói các đối tượng trong hai tài liệu tham khảo riêng biệt hơn nó cần. Có một sublass SoftReference đơn với equals() bình đẳng trong Google ConcurrentHashMap có thể sạch hơn theo cách này. –

1

Vì không có ConcurrentHashSet sử dụng tài liệu tham khảo mềm, chỉ có hai cách tiếp cận:

1.) cách tiếp cận của bạn với ConcurrentHashMap

  • Override equalshashCode trong SoftReference
  • Bên trong equalshashCode chỉ truy cập đối tượng bằng cách sử dụng SoftReference#get
  • Đặt SoftReference làm khóa và bất kỳ đối tượng nào làm giá trị (chỉ không cho phép null)
  • Nếu tham chiếu bị lỗi khi truy cập hashCode hoặc bằng, thêm tham chiếu vào hàng đợi xóa để thường xuyên xóa các phím đã chết.
  • Kiểm tra chứa qua containsKey

2.) Sử dụng ConcurrentMultimap<Integer, Set<SoftReference<RepLookupEntry>> và sử dụng hashCode làm khóa và tập hợp SoftReferences được đồng bộ hóa làm giá trị. Khi bạn nhận được số lần truy cập hashCode, hãy kiểm tra nội dung của tất cả SoftReferences để biết sự bình đẳng. Không phải là rất đẹp, tôi đồng ý và khôn lanh để đồng bộ hóa.

Nếu tôi ở vị trí của bạn, tôi sẽ không sử dụng SoftReferences chút nào, mà là ConcurrentHashMap để giữ tham chiếu mạnh mẽ cho các POJO của bạn. Mỗi lần một phần tử mới đến cũng đặt nó trong một ConcurrentLinkQueue. Nếu hàng đợi vượt quá giới hạn nhất định, hãy bắt đầu xóa các phần tử khỏi HashMap.