java - PassiveExpiringMap 不会使对象过期

标签 java collections apache-commons

我期待 org.apache.commons.collections4.map.PassiveExpiringMap 开箱即用。不幸的是,在最明显的对象按时过期的用例中,它对我不起作用。下面的代码创建了一个 5 秒的过期策略。测试等待 10 秒,这是所有 map 对象应该过期​​和删除的时间。但他们不是。

import org.apache.commons.collections4.map.PassiveExpiringMap;
import org.junit.Assert;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
    
public class PassiveExpiringMapTest {
    @Test
    public void givenDataMap_whenWrappingMapWithPassiveExpiringMap_thenObjectsAreRemovedWhenExpired() {
        
        final Map<String, Integer> m = new HashMap<>();
        m.put("one", Integer.valueOf(1));
        m.put("two", Integer.valueOf(2));
        m.put("three", Integer.valueOf(3));

        PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<String, Integer>
            expirationPolicy = new PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<>(
            5, TimeUnit.SECONDS);

        PassiveExpiringMap<String, Integer> expiringMap = new PassiveExpiringMap<>(expirationPolicy, m);

        int initialCapacity = expiringMap.size();
        System.out.println("initialCapacity = " + initialCapacity);
        Assert.assertEquals(3, initialCapacity);

        System.out.println("Sleeping...");
        try { Thread.sleep(10000L); } catch (InterruptedException e) { }

        int updatedCapacity = expiringMap.size();
        System.out.println("updatedCapacity = " + updatedCapacity);
        Integer one = expiringMap.get("one");
        Assert.assertNull(one);
        Assert.assertEquals(0, updatedCapacity);
    }
}

测试失败,输出如下:

initialCapacity = 3
Sleeping...
updatedCapacity = 3

java.lang.AssertionError: expected null, but was:<1>

    at org.junit.Assert.fail(Assert.java:88)
    at org.junit.Assert.failNotNull(Assert.java:755)
    at org.junit.Assert.assertNull(Assert.java:737)
    at org.junit.Assert.assertNull(Assert.java:747)

知道我错过了什么吗?

最佳答案

查看 PassiveExpiringMap 的源代码帮助我弄清楚了为什么我的原始版本不起作用。使用映射进行初始化会导致内部 expirationMap 字段为空。 expirationMap 必须包含每个对象的条目,以便逐出过期对象。为此,需要使用 put 方法。下面修改后的代码有效。请注意,对象直接添加到 expiringMap,而不是像以前那样添加到 HashMap:

import org.apache.commons.collections4.map.PassiveExpiringMap;
import org.junit.Assert;
import org.junit.Test;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

public class PassiveExpiringMapTest {

    @Test
    public void givenDataMap_whenWrappingMapWithPassiveExpiringMap_thenObjectsAreRemovedWhenExpired() {
        
        PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<String, Integer>
            expirationPolicy = new PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<>(
            5, TimeUnit.SECONDS);

        PassiveExpiringMap<String, Integer> expiringMap = new PassiveExpiringMap<>(expirationPolicy, new HashMap<>());
        expiringMap.put("one", Integer.valueOf(1));
        expiringMap.put("two", Integer.valueOf(2));
        expiringMap.put("three", Integer.valueOf(3));
        int initialCapacity = expiringMap.size();
        System.out.println("initialCapacity = " + initialCapacity);
        Assert.assertEquals(3, initialCapacity);

        System.out.println("Sleeping...");
        try { Thread.sleep(10000L); } catch (InterruptedException e) { }

        int updatedCapacity = expiringMap.size();
        System.out.println("updatedCapacity = " + updatedCapacity);
        Integer one = expiringMap.get("one");
        Assert.assertNull(one);
        Assert.assertEquals(0, updatedCapacity);
    }
}

关于java - PassiveExpiringMap 不会使对象过期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64667848/

相关文章:

java - Servlet 和后端关系

javascript - backbone.js:从集合中删除后保留元素

java - 如何在不迭代的情况下从 HashMap 中获取一个条目

java - 在Java中的Collections对象中声明类型参数两次

java - 上传前获取post参数

Java BeanUtils 带下划线 (_) 的未知属性

java - Apache 通用 CLI : How to add arguments?

java - 检查 Type 实例是否等于泛型类型

java - 使用 AspectJ 的 AOP 在 Spring 不起作用?

java - 如何从 jar 文件中获取 log4j 输出