ホームページ  >  記事  >  Java  >  Javaで有効期限マップを設定する方法

Javaで有効期限マップを設定する方法

WBOY
WBOY転載
2023-05-04 10:13:062948ブラウズ

1. 技術的背景

実際のプロジェクト開発では、システムの可用性と堅牢性の向上に役立つキャッシュ ミドルウェア (redis、MemCache など) をよく使用します。

しかし、多くの場合、プロジェクトが比較的単純であれば、システムの複雑さを増すためにキャッシュを使用するために Redis などのミドルウェアを特別に導入する必要はありません。それでは、Java 自体には便利な軽量キャッシュ コンポーネントがあるのでしょうか?

答えはもちろん「はい」であり、方法は複数あります。一般的なソリューションには、ExpiringMap、LoadingCache、および HashMap ベースのパッケージ化が含まれます。

2. 技術的効果

  • 古い削除戦略などのキャッシュの一般的な機能を実現します

  • ホット データのウォームアップ

3. ExpiringMap

3.1 関数の概要

  • マップ内のエントリは、一定期間後に自動的に期限切れになるように設定できます。時間。

  • マップの最大容量値を設定できます。最大サイズに達すると、値を再度挿入すると、マップ内の最初の値が期限切れになります。

  • リスニング イベントを追加し、エントリの有効期限が切れたときにリスニング機能をスケジュールできます。

  • 遅延読み込みを設定し、get() メソッドが呼び出されたときにオブジェクトを作成できます。

3.2 ソース コード

github アドレス

3.3 例

依存関係の追加 (Maven)

<dependency> 
    <groupId>net.jodah</groupId> 
    <artifactId>expiringmap</artifactId> 
    <version>0.5.8</version> 
</dependency>

例ソースコード

public class ExpiringMapApp {

    public static void main(String[] args) {
        // maxSize: 设置最大值,添加第11个entry时,会导致第1个立马过期(即使没到过期时间)
        // expiration:设置每个key有效时间10s, 如果key不设置过期时间,key永久有效。
        // variableExpiration: 允许更新过期时间值,如果不设置variableExpiration,不允许后面更改过期时间,一旦执行更改过期时间操作会抛异常UnsupportedOperationException
        // policy:
        //        CREATED: 只在put和replace方法清零过期时间
        //        ACCESSED: 在CREATED策略基础上增加, 在还没过期时get方法清零过期时间。
        //        清零过期时间也就是重置过期时间,重新计算过期时间.
        ExpiringMap<String, String> map = ExpiringMap.builder()
            .maxSize(10)
            .expiration(10, TimeUnit.SECONDS)
            .variableExpiration().expirationPolicy(ExpirationPolicy.CREATED).build();

        map.put("token", "lkj2412lj1412412nmlkjl2n34l23n4");
        map.put("name", "管理员", 20000, TimeUnit.SECONDS);

        // 模拟线程等待...
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("token ===> " + map.get("token"));
        System.out.println("name ===> " + map.get("name"));

        // 注意: 在创建map时,指定的那些参数如过期时间和过期策略都是全局的, 对map中添加的每一个entry都适用.
        //        在put一个entry键值对时可以对当前entry 单独设置 过期时间、过期策略,只对当前这个entry有效.
    }
}

実行結果

##token ===> null

name ===> 管理者

注意

マップを作成する場合、有効期限や有効期限ポリシーなどの指定されたパラメータはグローバルであり、マップに追加されるすべてのエントリに適用されます。
エントリのキーと値のペアを設定する場合、現在のエントリに対して有効期限と有効期限ポリシーを個別に設定できますが、これは現在のエントリに対してのみ有効です。

4. LoadingCache

4.1 機能の紹介

Google がオープンソース化したスレッドセーフなローカル キャッシュ ソリューション。

特徴: キャッシュのリサイクル メカニズム、キャッシュの読み込み/ヒット ステータスの監視、柔軟で強力な機能、シンプルで使いやすい API を提供します。

4.2 例

ソース コード

public class LoadingCacheApp {

    public static void main(String[] args) throws Exception {
        // maximumSize: 缓存池大小,在缓存项接近该大小时, Guava开始回收旧的缓存项
        // expireAfterAccess: 设置时间对象没有被读/写访问则对象从内存中删除(在另外的线程里面不定期维护)
        // removalListener: 移除监听器,缓存项被移除时会触发的钩子
        // recordStats: 开启Guava Cache的统计功能
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()
            .maximumSize(100)
            .expireAfterAccess(10, TimeUnit.SECONDS)
            .removalListener(new RemovalListener<String, String>() {
                @Override
                public void onRemoval(RemovalNotification<String, String> removalNotification) {
                    System.out.println("过时删除的钩子触发了... key ===> " + removalNotification.getKey());
                }
            })
            .recordStats()
            .build(new CacheLoader<String, String>() {
                // 处理缓存键不存在缓存值时的处理逻辑
                @Override
                public String load(String key) throws Exception {
                    return "不存在的key";
                }
            });

        cache.put("name", "小明");
        cache.put("pwd", "112345");

        // 模拟线程等待...
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("token ===> " + cache.get("name"));
        System.out.println("name ===> " + cache.get("pwd"));
    }
}

実行結果

古い削除フックがトリガーされました... key ===> name

token ===> 存在しないキー
廃止された削除フックがトリガーされました... key ===> pwd
name ===> 存在しないキー

4.3 削除メカニズム

guava がデータをキャッシュする場合、受動的削除と能動的削除の 2 種類のデータ削除があります。

パッシブ削除

  • サイズベースの削除: 数値が指定されたサイズに達すると、使用頻度の低いキー値が削除されます

  • 時間ベースの削除:expirateAfterAccess(long, TimeUnit) 最後のアクセスからの経過時間に基づいてキーと値のペアを削除します。 expireAfterWrite(long, TimeUnit) キーと値のペアが作成された後、または値が置き換えられた後の時間に基づいて削除します

  • 参照ベースの削除: 主に Java のガベージ コレクション メカニズムに基づいています。キーまたは値の参照関係に基づく削除

アクティブな削除

  • 個別に削除: Cache.invalidate(key)

  • バッチ削除: Cache.invalidateAll(keys)

  • すべて削除: Cache.invalidateAll()

If削除リスナー RemovalListener が設定されている場合、リスナーの下のロジックはすべての削除アクション中に同期して実行されます。

非同期に変更する必要がある場合は、RemovalListeners.asynchronous(RemovalListener, Executor) を使用します。

4.4 その他

  • put 操作の前に、このキー値を使用すると、removeListener が最初にトリガーされてリスナーが削除され、次に

  • がexpireAfterAccessとexpireAfterWriteで構成されますが、指定された時間が経過しても削除されません。

  • 削除ポリシー ロジック:

CacheBuilder によって構築されたキャッシュは、特定の時間に自動的にクリーニングとリサイクル作業を実行しません。特定の時間に実行されます。キャッシュ項目は有効期限が切れるとすぐにクリーンアップされます。第一にスレッドが比較的重いこと、第二に環境によってはスレッドの作成が制限されているため、キャッシュ メンテナンスのためのスレッドは開始されません。

書き込み操作中、または場合によっては読み取り操作中に、少量のメンテナンス作業を実行します。もちろん、独自のメンテナンス スレッドを作成し、一定の間隔で Cache.cleanUp() を呼び出すこともできます。

以上がJavaで有効期限マップを設定する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。