Menggunakan MapMaker Guava

1. Perkenalan

MapMaker adalah kelas pembangun di Guava yang memudahkan pembuatan peta yang aman untuk thread.

Java sudah mendukung WeakHashMap untuk menggunakan Referensi Lemah untuk kunci. Namun, tidak ada solusi out-of-the-box untuk menggunakan hal yang sama untuk nilai. Untungnya, Pencipta Peta menyediakan metode pembuat sederhana untuk menggunakan WeakReference baik untuk kunci maupun nilainya .

Dalam tutorial ini, mari kita lihat bagaimana Pencipta Peta mempermudah pembuatan banyak peta dan menggunakan referensi yang lemah.

2. Ketergantungan Maven

Pertama-tama, mari tambahkan dependensi Google Guava, yang tersedia di Maven Central:

 com.google.guava guava 29.0-jre 

3. Contoh Caching

Mari pertimbangkan skenario sederhana dari server yang mempertahankan beberapa cache untuk pengguna: cache sesi dan cache profil.

Cache sesi berumur pendek dengan entri menjadi tidak valid setelah pengguna tidak lagi aktif. Jadi cache bisa menghapus entri untuk pengguna setelah objek pengguna dikumpulkan sampah.

Namun, cache profil dapat memiliki time-to-live (TTL) yang lebih tinggi. Entri di cache profil menjadi tidak valid hanya ketika pengguna memperbarui profilnya.

Dalam kasus ini, cache dapat menghapus entri hanya jika objek profil dikumpulkan dari sampah.

3.1. Struktur data

Mari buat kelas untuk mewakili entitas ini.

Kami akan mulai dengan pengguna terlebih dahulu:

public class User { private long id; private String name; public User(long id, String name) { this.id = id; this.name = name; } public long getId() { return id; } public String getName() { return name; } }

Kemudian sesi:

public class Session { private long id; public Session(long id) { this.id = id; } public long getId() { return id; } } 

Dan terakhir profilnya:

public class Profile { private long id; private String type; public Profile(long id, String type) { this.id = id; this.type = type; } public long getId() { return id; } public String getName() { return type; } }

3.2. Membuat Cache

Mari buat instance ConcurrentMap untuk cache sesi menggunakan metode makeMap :

ConcurrentMap sessionCache = new MapMaker().makeMap();

Peta yang dikembalikan tidak mengizinkan nilai null untuk kunci dan nilainya.

Sekarang, mari buat instance ConcurrentMap lain untuk cache profil:

ConcurrentMap profileCache = new MapMaker().makeMap();

Perhatikan bahwa kami belum menentukan kapasitas awal untuk cache. Jadi, Pencipta Peta membuat peta dengan kapasitas 16 secara default.

Jika kita ingin kita dapat memodifikasi kapasitas menggunakan metode initialCapacity :

ConcurrentMap profileCache = new MapMaker().initialCapacity(100).makeMap();

3.3. Mengubah Tingkat Konkurensi

Pencipta Peta menetapkan nilai default untuk tingkat konkurensi ke 4 . Namun, sessionCache perlu mendukung lebih banyak pembaruan bersamaan tanpa pertentangan utas apa pun.

Di sini, metode pembangun concurrencyLevel datang untuk menyelamatkan:

ConcurrentMap sessionCache = new MapMaker().concurrencyLevel(10).makeMap();

3.4. Menggunakan Referensi Lemah

Peta yang kami buat di atas menggunakan referensi yang kuat untuk kunci dan nilai. Jadi, entri tetap ada di peta meskipun kunci dan nilainya dikumpulkan dari sampah. Sebagai gantinya kita harus menggunakan referensi yang lemah.

Sebuah sessionCache entri tidak valid setelah tombol (objek pengguna) adalah sampah-dikumpulkan. Jadi, mari gunakan referensi lemah untuk kunci:

ConcurrentMap sessionCache = new MapMaker().weakKeys().makeMap();

Untuk profileCache , kita dapat menggunakan referensi lemah untuk nilainya:

ConcurrentMap profileCache = new MapMaker().weakValues().makeMap();

When these references are garbage-collected, Guava guarantees that these entries will not be included in any of the subsequent read or write operations on the map. However, the size() method might sometimes be inconsistent and can include these entries.

4. MapMaker Internals

MapMaker creates a ConcurrentHashMap by default if weak references are not enabled. The equality checks happen via the usual equals method.

If we enable weak references, then MapMaker creates a custom map represented by a set of hash tables internally. It also shares similar performance characteristics as a ConcurrentHashMap.

Namun, perbedaan penting dengan WeakHashMap adalah pemeriksaan kesetaraan terjadi melalui perbandingan identitas (== dan identityHashCode ).

5. Kesimpulan

Dalam artikel singkat ini, kita belajar bagaimana menggunakan kelas Pencipta Peta untuk membuat peta yang aman untuk thread. Kami juga melihat bagaimana menyesuaikan peta untuk menggunakan referensi yang lemah.

Seperti biasa, kode sumber lengkap artikel tersedia di GitHub.