最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實現(xiàn)本地緩存的方式匯總

 更新時間:2023年07月28日 08:58:11   作者:qinxun2008081  
引入緩存,主要用于實現(xiàn)系統(tǒng)的高性能,高并發(fā),這篇文章主要介紹了Java實現(xiàn)本地緩存的幾種方式,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

一、概念

引入緩存,主要用于實現(xiàn)系統(tǒng)的高性能,高并發(fā)。將數(shù)據(jù)庫查詢出來的數(shù)據(jù)放入緩存服務(wù)中,因為緩存是存儲在內(nèi)存中的,內(nèi)存的讀寫性能遠(yuǎn)超磁盤的讀寫性能,所以訪問的速度非常快。但是電腦重啟后,內(nèi)存中的數(shù)據(jù)會全部清除,而磁盤中的數(shù)據(jù)雖然讀寫性能很差,但是數(shù)據(jù)不會丟失。

二、手寫本地緩存

首先創(chuàng)建一個緩存實體類

package com.example.vuespringboot.bean;
import lombok.Data;
/**
 * @author qx
 * @date 2023/7/27
 * @des 自定義緩存實體類
 */
@Data
public class MyCache {
    /**
     * 鍵
     */
    private String key;
    /**
     * 值
     */
    private Object value;
    /**
     * 過期時間
     */
    private Long expireTime;
}

接著我們編寫一個緩存操作的工具類

package com.example.vuespringboot.util;
import com.example.vuespringboot.bean.MyCache;
import java.time.Duration;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
 * @author qx
 * @date 2023/7/27
 * @des 自定義本地緩存工具類
 */
public class CacheUtil {
    /**
     * 緩存數(shù)據(jù)Map
     */
    private static final Map<String, MyCache> CACHE_MAP = new ConcurrentHashMap<>();
    /**
     * 定時器線程池,用于清除過期緩存
     */
    private static final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    static {
        // 注冊一個定時線程任務(wù),服務(wù)啟動1秒之后,每隔500毫秒執(zhí)行一次
        // 定時清理過期緩存
        executorService.scheduleAtFixedRate(CacheUtil::clearCache, 1000, 500, TimeUnit.MILLISECONDS);
    }
    /**
     * 添加緩存
     *
     * @param key    緩存鍵
     * @param value  緩存值
     * @param expire 過期時間,單位秒
     */
    public static void put(String key, Object value, long expire) {
        MyCache myCache = new MyCache();
        myCache.setKey(key);
        myCache.setValue(value);
        if (expire > 0) {
            long expireTime = System.currentTimeMillis() + Duration.ofSeconds(expire).toMillis();
            myCache.setExpireTime(expireTime);
        }
        CACHE_MAP.put(key, myCache);
    }
    /**
     * 獲取緩存
     *
     * @param key 緩存鍵
     * @return 緩存數(shù)據(jù)
     */
    public static Object get(String key) {
        if (CACHE_MAP.containsKey(key)) {
            return CACHE_MAP.get(key).getValue();
        }
        return null;
    }
    /**
     * 移除緩存
     *
     * @param key 緩存鍵
     */
    public static void remove(String key) {
        CACHE_MAP.remove(key);
    }
    /**
     * 清理過期的緩存數(shù)據(jù)
     */
    private static void clearCache() {
        if (CACHE_MAP.size() <= 0) {
            return;
        }
        // 判斷是否過期 過期就從緩存Map刪除這個元素
        CACHE_MAP.entrySet().removeIf(entry -> entry.getValue().getExpireTime() != null && entry.getValue().getExpireTime() > System.currentTimeMillis());
    }
}

最后,我們來測試一下緩存服務(wù)

package com.example.vuespringboot;
import com.example.vuespringboot.util.CacheUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.TimeUnit;
@SpringBootTest
class VueSpringBootApplicationTests {
    @Test
    void contextLoads() throws InterruptedException {
        // 寫入緩存數(shù)據(jù) 2秒后過期
        CacheUtil.put("name", "qx", 2);
        Object value1 = CacheUtil.get("name");
        System.out.println("第一次查詢結(jié)果:" + value1);
        // 停頓3秒
        TimeUnit.SECONDS.sleep(3);
        Object value2 = CacheUtil.get("name");
        System.out.println("第二次查詢結(jié)果:" + value2);
    }
}

啟動測試,我們從控制臺的返回看到輸出結(jié)果和我們的預(yù)期一致!

第一次查詢結(jié)果:qx
第二次查詢結(jié)果:null

實現(xiàn)思路其實很簡單,采用ConcurrentHashMap作為緩存數(shù)據(jù)存儲服務(wù),然后開啟一個定時調(diào)度,每隔500毫秒檢查一下過期的緩存數(shù)據(jù),然后清除掉!

三、基于Guava Cache實現(xiàn)本地緩存

相比自己編寫的緩存服務(wù),Guava Cache 要強大的多,支持很多特性如下:

  • 支持最大容量限制
  • 支持兩種過期刪除策略(插入時間和讀取時間)
  • 支持簡單的統(tǒng)計功能
  • 基于 LRU 算法實現(xiàn)

1.添加gugva的依賴

 <!--guava-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>31.1-jre</version>
        </dependency>

2.測試

    @Test
    void testGuava() throws ExecutionException, InterruptedException {
        // 創(chuàng)建一個緩存實例
        Cache<String, String> cache = CacheBuilder.newBuilder()
                // 初始容量
                .initialCapacity(5)
                // 最大緩存數(shù),超出淘汰
                .maximumSize(10)
                // 過期時間 設(shè)置寫入3秒后過期
                .expireAfterWrite(3, TimeUnit.SECONDS)
                .build();
        // 寫入緩存數(shù)據(jù)
        cache.put("name", "qq");
        // 讀取緩存數(shù)據(jù)
        String value1 = cache.get("name", () -> "key過期");
        System.out.println("第一次查詢結(jié)果:" + value1);
        // 停頓4秒
        TimeUnit.SECONDS.sleep(4);
        // 讀取緩存數(shù)據(jù)
        String value2 = cache.get("name", () -> "key過期");
        System.out.println("第二次查詢結(jié)果:" + value2);
    }

啟動測試,我們從控制臺的返回看到輸出結(jié)果和我們的預(yù)期一致!

第一次查詢結(jié)果:qq
第二次查詢結(jié)果:key過期

四、基于 Caffeine 實現(xiàn)本地緩存

Caffeine 是基于 java8 實現(xiàn)的新一代緩存工具,緩存性能接近理論最優(yōu),可以看作是 Guava Cache 的增強版,功能上兩者類似,不同的是 Caffeine 采用了一種結(jié)合 LRU、LFU 優(yōu)點的算法:W-TinyLFU,在性能上有明顯的優(yōu)越性。

1.引入Caffeine

   <!--caffeine-->
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.9.3</version>
        </dependency>

2.測試

  @Test
    void testCaffeine() throws InterruptedException {
        // 創(chuàng)建一個緩存實例
        Cache<String, String> cache = Caffeine.newBuilder()
                // 初始容量
                .initialCapacity(5)
                // 最大緩存數(shù),超出淘汰
                .maximumSize(10)
                // 設(shè)置緩存寫入間隔多久過期
                .expireAfterWrite(3, TimeUnit.SECONDS)
                // 設(shè)置緩存最后訪問后間隔多久淘汰,實際很少用到
                .build();
        // 寫入緩存數(shù)據(jù)
        cache.put("userName", "張三");
        // 讀取緩存數(shù)據(jù)
        String value1 = cache.get("userName", (key) -> {
            // 如果key不存在,會執(zhí)行回調(diào)方法
            return "key已過期";
        });
        System.out.println("第一次查詢結(jié)果:" + value1);
        // 停頓4秒
        Thread.sleep(4000);
        // 讀取緩存數(shù)據(jù)
        String value2 = cache.get("userName", (key) -> {
            // 如果key不存在,會執(zhí)行回調(diào)方法
            return "key已過期";
        });
        System.out.println("第二次查詢結(jié)果:" + value2);
    }

輸出結(jié)果:

第一次查詢結(jié)果:張三
第二次查詢結(jié)果:key已過期

五、基于 Encache 實現(xiàn)本地緩存

1.引入ehcache依賴

 <!--ehcache-->
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>3.9.7</version>
        </dependency>

2.自定義過期策略實現(xiàn)

package com.example.vuespringboot.util;
import org.ehcache.expiry.ExpiryPolicy;
import java.time.Duration;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
/**
 * @author qx
 * @date 2023/7/27
 * @des 自定義過期策略實現(xiàn)
 */
public class CustomExpiryPolicy<K, V> implements ExpiryPolicy<K, V> {
    private final Map<K, Duration> keyExpireMap = new ConcurrentHashMap();
    public Duration setExpire(K key, Duration duration) {
        return keyExpireMap.put(key, duration);
    }
    public Duration getExpireByKey(K key) {
        return Optional.ofNullable(keyExpireMap.get(key))
                .orElse(null);
    }
    public Duration removeExpire(K key) {
        return keyExpireMap.remove(key);
    }
    @Override
    public Duration getExpiryForCreation(K key, V value) {
        return Optional.ofNullable(getExpireByKey(key))
                .orElse(Duration.ofNanos(Long.MAX_VALUE));
    }
    @Override
    public Duration getExpiryForAccess(K key, Supplier<? extends V> value) {
        return getExpireByKey(key);
    }
    @Override
    public Duration getExpiryForUpdate(K key, Supplier<? extends V> oldValue, V newValue) {
        return getExpireByKey(key);
    }
}

3.測試

package com.example.vuespringboot.util;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import java.time.Duration;
/**
 * @author qx
 * @date 2023/7/27
 * @des 測試Encache
 */
public class EncacheTest {
    public static void main(String[] args) throws InterruptedException {
        String userCache = "userCache";
        // 自定義過期策略
        CustomExpiryPolicy<Object, Object> customExpiryPolicy = new CustomExpiryPolicy<>();
        // 聲明一個容量為20的堆內(nèi)緩存配置
        CacheConfigurationBuilder configurationBuilder = CacheConfigurationBuilder
                .newCacheConfigurationBuilder(String.class, String.class, ResourcePoolsBuilder.heap(20))
                .withExpiry(customExpiryPolicy);
        // 初始化一個緩存管理器
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                // 創(chuàng)建cache實例
                .withCache(userCache, configurationBuilder)
                .build(true);
        // 獲取cache實例
        Cache<String, String> cache = cacheManager.getCache(userCache, String.class, String.class);
        // 獲取過期策略
        CustomExpiryPolicy expiryPolicy = (CustomExpiryPolicy) cache.getRuntimeConfiguration().getExpiryPolicy();
        // 寫入緩存數(shù)據(jù)
        cache.put("userName", "張三");
        // 設(shè)置3秒過期
        expiryPolicy.setExpire("userName", Duration.ofSeconds(3));
        // 讀取緩存數(shù)據(jù)
        String value1 = cache.get("userName");
        System.out.println("第一次查詢結(jié)果:" + value1);
        // 停頓4秒
        Thread.sleep(4000);
        // 讀取緩存數(shù)據(jù)
        String value2 = cache.get("userName");
        System.out.println("第二次查詢結(jié)果:" + value2);
    }
}

輸出結(jié)果:

第一次查詢結(jié)果:張三
第二次查詢結(jié)果:null

到此這篇關(guān)于Java實現(xiàn)本地緩存的幾種方式的文章就介紹到這了,更多相關(guān)java本地緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 初識JAVA數(shù)組

    初識JAVA數(shù)組

    java語言中,數(shù)組是一種最簡單的復(fù)合數(shù)據(jù)類型。數(shù)組是有序數(shù)據(jù)的集合,數(shù)組中的每個元素具有相同的數(shù)據(jù)類型,可以用一個統(tǒng)一的數(shù)組名和下標(biāo)來唯一地確定數(shù)組中的元素。數(shù)組有一維數(shù)組和多維數(shù)組。
    2014-08-08
  • mybatis-plus多表關(guān)聯(lián)查詢功能的實現(xiàn)

    mybatis-plus多表關(guān)聯(lián)查詢功能的實現(xiàn)

    本文給大家介紹mybatis-plus多表關(guān)聯(lián)查詢功能的實現(xiàn)代碼,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-11-11
  • Java線程間協(xié)作wait、notify和notifyAll詳解

    Java線程間協(xié)作wait、notify和notifyAll詳解

    這篇文章主要介紹了Java線程間協(xié)作wait、notify和notifyAll詳解,在 Java 中可以用 wait、notify 和 notifyAll 來實現(xiàn)線程間的通信,盡管關(guān)于wait和notify的概念很基礎(chǔ),它們也都是Object類的函數(shù),但用它們來寫代碼卻并不簡單,,需要的朋友可以參考下
    2023-10-10
  • Spring Data JPA 設(shè)置字段默認(rèn)值方式

    Spring Data JPA 設(shè)置字段默認(rèn)值方式

    這篇文章主要介紹了Spring Data JPA設(shè)置字段默認(rèn)值方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java多線程Semaphore工具的使用詳解

    Java多線程Semaphore工具的使用詳解

    Semaphore 是一種用于控制線程并發(fā)訪問數(shù)的同步工具。它通過維護(hù)一定數(shù)量的許可證來限制對共享資源的訪問,許可證的數(shù)量就是可以同時訪問共享資源的線程數(shù)目,需要的朋友可以參考下
    2023-05-05
  • Java中處理日期時間的幾種操作技巧

    Java中處理日期時間的幾種操作技巧

    日期和時間是幾乎所有應(yīng)用程序中都會遇到的問題,從簡單的顯示當(dāng)前時間,到復(fù)雜的日期計算和時區(qū)處理,日期時間操作是開發(fā)中不可避免的一部分,Java提供了不同的工具來幫助我們處理日期和時間,本文為大家詳細(xì)說說,需要的朋友可以參考下
    2026-01-01
  • 基于springboot與axios的整合問題

    基于springboot與axios的整合問題

    這篇文章主要介紹了springboot與axios的整合問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java中ArrayList和LinkedList的區(qū)別

    Java中ArrayList和LinkedList的區(qū)別

    ArrayList和LinkedList在這個方法上存在一定的性能差異,本文就介紹了Java中ArrayList和LinkedList的區(qū)別,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • mybatis-sqlserver批量新增返回id方式

    mybatis-sqlserver批量新增返回id方式

    這篇文章主要介紹了mybatis-sqlserver批量新增返回id方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • spring?boot?mybatis日志輸出到控制臺的方法實踐

    spring?boot?mybatis日志輸出到控制臺的方法實踐

    在開發(fā)過程中我們往往需要打印出SQL語句,這樣就方便我們監(jiān)控問題,本文主要介紹了spring?boot?mybatis日志輸出到控制臺的方法實踐,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05

最新評論

怀宁县| 寿光市| 会理县| 阿克| 厦门市| 禄劝| 阳朔县| 合江县| 任丘市| 泰来县| 保德县| 房产| 永济市| 舟曲县| 铜山县| 潢川县| 双柏县| 塘沽区| 顺义区| 鸡东县| 长兴县| 安庆市| 兴义市| 云浮市| 盐城市| 垣曲县| 马龙县| 玉林市| 泰宁县| 玉山县| 兰西县| 上林县| 大同市| 赤水市| 随州市| 临江市| 富顺县| 汾西县| 赤壁市| 伊宁市| 舒城县|