Maison  >  Article  >  Java  >  Comment définir la carte du délai d'expiration en Java

Comment définir la carte du délai d'expiration en Java

WBOY
WBOYavant
2023-05-04 10:13:063000parcourir

1. Contexte technique

Dans le développement de projets réels, nous utilisons souvent des middlewares de cache (tels que redis, MemCache, etc.) pour nous aider à améliorer la disponibilité et la robustesse du système.

Mais dans de nombreux cas, si le projet est relativement simple, il n'est pas nécessaire d'introduire spécifiquement un middleware tel que Redis pour augmenter la complexité du système afin d'utiliser la mise en cache. Java lui-même dispose-t-il donc de composants de mise en cache légers et utiles ?

La réponse est bien sûr oui, et il existe plusieurs façons. Les solutions courantes incluent : ExpiringMap, LoadingCache et un packaging basé sur HashMap.

2. Effet technique

  • Implémenter des fonctions courantes du cache, telles qu'une stratégie de suppression obsolète

  • #🎜🎜 #
  • échauffement des données chaudes

3. ExpiringMap

3.1 Introduction à la fonction

#🎜 🎜#
    Vous pouvez configurer l'entrée dans la carte pour qu'elle expire automatiquement après un certain temps.
  • Vous pouvez définir la valeur de capacité maximale de la carte. Lorsque la taille maximale est atteinte, insérer à nouveau une valeur entraînera l'expiration de la première valeur de la carte.
  • Vous pouvez ajouter des événements d'écoute et programmer la fonction d'écoute à l'expiration de l'entrée.
  • Vous pouvez configurer le chargement différé et créer des objets lorsque la méthode get() est appelée.
  • 3.2 Code source

adresse github

3.3 Exemple

Ajouter une dépendance ( Maven )

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

Exemple de code source

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有效.
    }
}

Résultat d'exécution

token ===> == > Administrateur


Note

Lors de la création d'une carte, les paramètres spécifiés tels que l'heure d'expiration et la politique d'expiration sont globaux et s'appliquent à chaque entrée ajoutée à la carte. En vigueur.
Lors de la mise d'une paire clé-valeur d'entrée, vous pouvez définir le délai d'expiration et la politique d'expiration séparément pour l'entrée actuelle, qui n'est valable que pour l'entrée actuelle


4. LoadingCache#🎜. 🎜#
4.1 Introduction aux fonctions

Une solution de cache local thread-safe open source par Google.

Caractéristiques : Fournit un mécanisme de recyclage du cache, surveille l'état de chargement/d'accès du cache, des fonctions flexibles et puissantes, une API simple et facile à utiliser.

4.2 Exemple

Code source

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"));
    }
}

Résultat d'exécution

Le hook de suppression obsolète s'est déclenché.. . key ===> nom

token ===> Clé inexistante

hook de suppression obsolète déclenché... key ===> Clé inexistante


4.3 Mécanisme de suppression

Lorsque Guava met en cache des données, il existe deux types de suppression de données : la suppression passive et la suppression active.

Suppression passive

Suppression basée sur la taille : lorsque la quantité atteint la taille spécifiée, les valeurs clés rarement utilisées seront supprimées#🎜 🎜 #

    Suppression basée sur le temps : expireAfterAccess(long, TimeUnit) supprime une paire clé-valeur en fonction du temps écoulé après le dernier accès. expireAfterWrite(long, TimeUnit) Supprimer en fonction du temps écoulé après la création d'une paire clé-valeur ou le remplacement de la valeur
  • Suppression basée sur les références : principalement basée sur Java. Le mécanisme de récupération de place détermine la suppression en fonction de la relation de référence de la clé ou de la valeur. Suppression : Cache.invalidate(key)
  • Suppression par lots : Cache.invalidateAll(keys)#. 🎜🎜#
  • #🎜🎜 #Remove all: Cache.invalidateAll()

Si l'écouteur de suppression RemovalListener est configuré, toutes les actions de suppression sera exécuté de manière synchrone selon la logique de l'écouteur.

    Si vous devez passer en mode asynchrone, utilisez : RemovalListeners.asynchronous(RemovalListener, Executor).
  • 4.4 Autres

  • # 🎜🎜 #Avant l'opération put, si la valeur de la clé existe déjà, RemoveListener sera d'abord déclenché pour supprimer l'écouteur, puis ajouter

  • expireAfterAccess et expireAfterWrite sont configurés, mais à l'heure indiquée n'a pas été supprimé plus tard.

Logique de la stratégie de suppression :

Le cache créé par CacheBuilder n'effectuera pas automatiquement le nettoyage et le recyclage à un moment spécifique time Il ne nettoiera pas un élément de cache immédiatement après son expiration et ne démarrera pas de thread pour la maintenance du cache, car d'une part, le thread est relativement lourd et, d'autre part, certains environnements limitent la création de threads.

Il effectuera accidentellement une petite quantité de travaux de maintenance lors des opérations d'écriture, ou occasionnellement lors des opérations de lecture. Bien entendu, vous pouvez également créer votre propre thread de maintenance et appeler Cache.cleanUp() à intervalles fixes.

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer