Guava CacheBuilder移除侦听器 [英] Guava CacheBuilder removal listener

查看:188
本文介绍了Guava CacheBuilder移除侦听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请告诉我我缺少什么。

我在DataPool中有一个由CacheBuilder建立的缓存。 DataPool是一个单例对象,其各种线程可以获取实例并对其执行操作。现在,我只有一个线程来生成数据并将其添加到所说的缓存中。

I have a cache build by CacheBuilder inside a DataPool. DataPool is a singleton object whose instance various thread can get and act on. Right now I have a single thread which produces data and add this into the said cache.

要显示代码的相关部分:

To show the relevant part of the code:

 private InputDataPool(){

    cache=CacheBuilder.newBuilder().expireAfterWrite(1000, TimeUnit.NANOSECONDS).removalListener(
            new RemovalListener(){
                {
                    logger.debug("Removal Listener created");
                }
                                public void onRemoval(RemovalNotification notification) {
                                    System.out.println("Going to remove data from InputDataPool");
                                    logger.info("Following data is being removed:"+notification.getKey());
                                    if(notification.getCause()==RemovalCause.EXPIRED)
                                    {
                                        logger.fatal("This data expired:"+notification.getKey());
                                    }else
                                    {
                                        logger.fatal("This data didn't expired but evacuated intentionally"+notification.getKey());
                                    }

                                }}
                    ).build(new CacheLoader(){

                        @Override
                        public Object load(Object key) throws Exception {
                                logger.info("Following data being loaded"+(Integer)key);
                                Integer uniqueId=(Integer)key;
                                return InputDataPool.getInstance().getAndRemoveDataFromPool(uniqueId);

                        }

                    });
}

public static InputDataPool getInstance(){
        if(clsInputDataPool==null){
            synchronized(InputDataPool.class){
                if(clsInputDataPool==null)
                {
                    clsInputDataPool=new InputDataPool();
                }
            }
        }
    return clsInputDataPool;
}

在上述线程中,调用就像

From the said thread the call being made is as simple as

 while(true){
 inputDataPool.insertDataIntoPool(inputDataPacket);
     //call some logic which comes with inputDataPacket and sleep for 2 seconds.
}

其中inputDataPool.insertDataIntoPool就像

and where inputDataPool.insertDataIntoPool is like

inputDataPool.insertDataIntoPool(InputDataPacket inputDataPacket){ 
 cache.get(inputDataPacket.getId());
}

现在的问题是,缓存中的元素应该在1000纳秒后过期因此,当第二次调用inputDataPool.insertDataIntoPool时,第一次插入的数据将被撤离,因为它必须在插入2秒后由于调用已过期而失效,然后应调用相应的Removal Listener。
但这没有发生。我调查了缓存统计信息,无论cache.get(id)被调用了多少时间,evictionCount始终为零。

Now the question is, the element in cache is supposed to expire after 1000 nanosec.So when inputDataPool.insertDataIntoPool is called second time, the data which has been inserted first time will be evacuated as it must have got expired as the call is being after 2 seconds of its insertion.And then correspondingly Removal Listener should be called. But this is not happening. I looked into cache stats and evictionCount is always zero, no matter how much time cache.get(id) is called.

但是重要的是,如果我扩展inputDataPool.insertDataIntoPool

But importantly, if I extend inputDataPool.insertDataIntoPool

  inputDataPool.insertDataIntoPool(InputDataPacket inputDataPacket){ 
 cache.get(inputDataPacket.getId());
    try{
     Thread.sleep(2000);
   }catch(InterruptedException ex){ex.printStackTrace();
     }
cache.get(inputDataPacket.getId())
}

然后驱逐将按预期方式进行,并调用了移除侦听器。

then the eviction take place as expected with removal listener being called.

现在,我很茫然,想念这样的事情一种行为。

Now I'm very much clueless at the moment where I'm missing something to expect such kind of behaviour. Please help me see,if you see something.

P.S。请忽略任何错别字。也不会进行检查,也不会使用任何泛型,所有这些都只是在测试CacheBuilder功能的阶段。

P.S. Please ignore any typos.Also no check is being made, no generic has been used, all as this is just in the phase of testing the CacheBuilder functionality.

感谢

推荐答案

如javadoc和用户指南,没有线程可以确保在延迟时间过后立即从缓存中删除条目。取而代之的是,如果写操作很少,则在写操作期间删除条目,有时在读操作期间删除条目。这是为了实现高吞吐量和低延迟。当然,每个写操作都不会导致清除:

As explained in the javadoc and in the user guide, There is no thread that makes sure entries are removed from the cache as soon as the delay has elapsed. Instead, entries are removed during write operations, and occasionally during read operations if writes are rare. This is to allow for a high throughput and a low latency. And of course, every write operation doesn't cause a cleanup:


使用CacheBuilder构建的缓存不会执行清除和逐出值
自动,或在值过期后立即进行,或任何
排序。相反,它在
写操作期间或偶尔进行的读操作中执行少量维护,如果写操作很少

Caches built with CacheBuilder do not perform cleanup and evict values "automatically," or instantly after a value expires, or anything of the sort. Instead, it performs small amounts of maintenance during write operations, or during occasional read operations if writes are rare.

原因是如下所示:如果我们要连续执行Cache
维护,则需要创建一个线程,其
操作将与用户操作竞争共享锁。
此外,某些环境限制了线程的创建,
会使CacheBuilder在该环境中不可用。

The reason for this is as follows: if we wanted to perform Cache maintenance continuously, we would need to create a thread, and its operations would be competing with user operations for shared locks. Additionally, some environments restrict the creation of threads, which would make CacheBuilder unusable in that environment.

这篇关于Guava CacheBuilder移除侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆