Java記憶體快取-通過Google Guava建立快取

小碼農薛堯發表於2019-08-23

谷歌Guava快取

Guava介紹

Guava是Google guava中的一個記憶體快取模組,用於將資料快取到JVM記憶體中。實際專案開發中經常將一些公共或者常用的資料快取起來方便快速訪問。

Java記憶體快取-通過Google Guava建立快取

Guava Cache是單個應用執行時的本地快取。它不把資料存放到檔案或外部伺服器。如果不符合需求,可以選擇Memcached、Redis等工具。

小案例

pom.xml新增guava依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>me.xueyao.cache</groupId>
    <artifactId>java-demo</artifactId>
    <version>1.0.0</version>

    <dependencies>
        <dependency>
            <groupId>javax.cache</groupId>
            <artifactId>cache-api</artifactId>
            <version>1.1.0</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>27.0.1-jre</version>
        </dependency>
    </dependencies>
</project>
複製程式碼

GuavaCacheDemo.java 程式碼如下:

package me.xueyao.cache.java.guava;

import com.google.common.cache.*;
import me.xueyao.cache.java.pojo.User;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @author simon
 * https://github.com/google/guava
 */
public class GuavaCacheDemo {
    public static void main(String[] args) throws ExecutionException {
        //快取介面這裡是LoadingCache,LoadingCache在快取項不存在時可以自動載入快取
        LoadingCache<String, User> userCache
                //CacheBuilder的建構函式是私有的,只能通過其靜態方法newBuilder()來獲得CacheBuilder的例項
                = CacheBuilder.newBuilder()
                //設定併發級別為8,併發級別是指可以同時寫快取的執行緒數
                .concurrencyLevel(8)
                //設定寫快取後8秒鐘過期
                .expireAfterWrite(8, TimeUnit.SECONDS)
                //設定寫快取後1秒鐘重新整理
                .refreshAfterWrite(1, TimeUnit.SECONDS)
                //設定快取容器的初始容量為5
                .initialCapacity(5)
                //設定快取最大容量為100,超過100之後就會按照LRU最近雖少使用演算法來移除快取項
                .maximumSize(100)
                //設定要統計快取的命中率
                .recordStats()
                //設定快取的移除通知
                .removalListener(new RemovalListener<Object, Object>() {
                    @Override
                    public void onRemoval(RemovalNotification<Object, Object> notification) {
                        System.out.println(notification.getKey() + " 被移除了,原因: " + notification.getCause());
                    }
                })
                //build方法中可以指定CacheLoader,在快取不存在時通過CacheLoader的實現自動載入快取
                .build(
                        new CacheLoader<String, User>() {
                            @Override
                            public User load(String key) throws Exception {
                                System.out.println("快取沒有時,從資料庫載入" + key);
                                return new User("tony" + key, key);
                            }
                        }
                );

        // 第一次讀取
        for (int i = 0; i < 10; i++) {
            User user = userCache.get("uid" + i);
            System.out.println(user);
        }

        // 第二次讀取
        for (int i = 0; i < 10; i++) {
            User user = userCache.get("uid" + i);
            System.out.println(user);
        }
        System.out.println("cache stats:");
        //最後列印快取的命中率等 情況
        System.out.println(userCache.stats().toString());
    }
}
複製程式碼

User.java 程式碼如下:

package me.xueyao.cache.java.pojo;

import java.io.Serializable;

/**
 * @author simon
 */
public class User implements Serializable {
    private String userName;
    private String userId;

    public User(String userName, String userId) {
        this.userName = userName;
        this.userId = userId;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    @Override
    public String toString() {
        return userId + " --- " + userName;
    }
}
複製程式碼

執行後的結果如下:

Java記憶體快取-通過Google Guava建立快取

第一次迴圈時快取中沒有資料,構建了快取,第二次直接命中快取。如果程式需要單機記憶體快取,可以用該方式構建快取。

相關文章