Mục lục
Trong bài viết này chúng ta sẽ cùng nhau tìm hiểu về WeakHashMap trong Java, sau đó chúng ta sẽ cùng xem cách mà các hệ thống cache sử dụng WeakHashMap để tối ưu bộ nhớ như thế nào,
Về cơ bản thì WeakHashMap là một hashtable-based implementation của Map interface với key có kiểu dữ liệu là WeakReference.
Một phần tử trong WeakHashMap sẽ tự động bị xóa khi key của nó không còn được sử dụng nữa, nghĩa là không có một tham chiếu trỏ đến key này. Điều này làm cho WeakHashMap khác biệt so với các Map implementation khác.
Strong, Soft, and Weak References
Để hiểu rõ cách hoạt động của WeakHashMap chúng ta cần nắm rõ WeakReference class và các khái niệm xoay quanh Strong, Soft và weak reference.
Strong References
Strong reference là một loại tham chiếu được dùng hằng ngày trong các mã nguồn Java:
Integer prime = 1;
Biến prime có kiểu strong reference tham chiếu đến một Integer object có giá trị là 1. Bất kỳ một object nào được tham chiếu bởi một strong reference sẽ không thể bị trình thu gom rác dọn dẹp.
Soft Reference
Một object được tham chiếu bởi một Soft reference sẽ bị trình thu gom rác thu gon khi JVM thực sự cần bộ nhớ.
Integer prime = 1; SoftReference<Integer> soft = new SoftReference<Integer>(prime); prime = null;
Trong ví dụ trên, prime object được tham chiếu bởi strong reference. Tiếp theo chúng ta đóng gói prime object bên trong một soft reference. Sau khi trỏ strong reference đến null, thì prime object sẽ được trình gom rác thu gom khi JVM cần thêm bộ nhớ.
Weak References
Một object được tham chiếu bởi weak reference sẽ bị trình thu gom rác thu gom khi mà không cần thiết phải chờ đến khi JVM cần thêm bộ nhớ.
Integer prime = 1; WeakReference<Integer> weak = new WeakReference<Integer>(prime); prime = null;
Khi chúng ta trỏ prime đến null, prime object sẽ bị xóa bởi trình thu gom rác ở lần chu kỳ tiếp theo của nó.
Các key trong WeakHashMap sử dụng đều sử dụng weak reference làm kiểu tham chiếu.
WeakHashMap trong hệ thống cache
Giả sử chúng ta xây dựng một hệ thống cache hình ảnh, với key là tên hình ảnh và value là hình ảnh tương ứng. Trong hệ thống này việc sử dụng HashMap sẽ không phải là một lựa chọn tốt vì các phần tử luôn được giữ lại ngay cả khi chúng không còn được sử dụng trong thời gian dài dẫn đến việc cạn kiệt bộ nhớ.
Sử dụng WeakHashMap cho phép chúng ta tận dụng được cơ chế của trình thu gom rác, các phần tử không còn được sử dụng trong thời gian dài sẽ bị trình thu gom rác dọn dẹp tự động mà chúng ta không cần phải triển khai một số chức năng thủ công để thực hiện công việc tương tự.
WeakHashMap<UniqueImageName, BigImage> map = new WeakHashMap<>(); BigImage bigImage = new BigImage("image_id"); UniqueImageName imageName = new UniqueImageName("name_of_big_image"); map.put(imageName, bigImage); assertTrue(map.containsKey(imageName)); imageName = null; System.gc(); await().atMost(10, TimeUnit.SECONDS).until(map::isEmpty);
Trong đoạn code minh họa trên, WeakHashMap được dùng để lưu BigImage object là value và imageName là key. Trong trường hợp chúng ta gán imageName = null thì phần tử với key tương ứng imageName sẽ bị xóa tự động.
Nguồn