番石榴CacheBuilder去除监听(Guava CacheBuilder removal lis

2019-09-17 07:27发布

请告诉我在哪里,我失去了一些东西。

我有CacheBuilder数据池内部的缓存版本。 数据池是一个单独的对象,其实例各种线程可以获取并采取行动。 现在我有它产生的数据,并添加到缓存中说这是一个单独的线程。

要显示代码的相关部分:

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

从上述线程正在发出这一呼吁的就是这么简单

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

并在inputDataPool.insertDataIntoPool像

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

现在的问题是,在高速缓存中的元素应该当inputDataPool.insertDataIntoPool被称为第二次在1000 nanosec.So到期,已插入的第一时间将撤离,因为它肯定有我作为过期呼叫正在后的数据其insertion.And 2秒钟,然后相应地删除监听器应该被调用。 但是,这没有发生。 我看着高速缓存的统计信息和evictionCount始终为零,不管cache.get(ID)多少时间被调用。

但重要的是,如果我延长inputDataPool.insertDataIntoPool

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

那么驱逐发生与去除听众被称为预期。

现在我在这里,我失去了一些东西期待这类行为的当下非常无能。 请帮我看看,如果你看到的东西。

PS请忽略任何typos.Also没有检查正在进行,没有通用已被使用,所有因为这只是在测试CacheBuilder功能的阶段。

谢谢

Answer 1:

正如Javadoc和在解释用户指南 ,没有线程确保条目从缓存中一旦延迟过去删除。 取而代之的是,在写操作时被删除的条目,偶尔在读操作期间如果写是罕见的。 这是为了让高吞吐量和低时延。 当然,每一个写操作不会导致清理:

与CacheBuilder内置缓存不执行清理和驱逐值“自动”或价值过期后立即,或诸如此类的事。 相反,它在写操作期间执行少量维修,或在偶尔的读操作,如果写是罕见的。

其原因如下:如果我们想继续进行缓存维护,我们需要创建一个线程,它的行动将与共享锁用户操作来竞争。 此外,一些环境限制线程的创建,这将使CacheBuilder在那种环境下无法使用。



Answer 2:

我有同样的问题,我可以在番石榴对CacheBuilder.removalListener文档发现这

警告:调用此方法后,不要继续使用此缓存建设者参考; 代替使用该方法返回参考。 在运行时,这些都指向同一个实例,但只能返回参考具有正确的泛型类型的信息,以确保类型安全。 为了达到最佳效果,请使用上述类文档中说明的标准方法链式成语,配置建设者和构建缓存在一个单独的语句。 不注意这些建议可能会导致一个ClassCastException被高速缓存操作在未来某个不确定的点抛出。

因此,通过改变代码中使用,它是将removalListnener这个问题可以得到解决后称为建设者参考

 CacheBuilder builder=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());
                                    }

                                }}
                    );
   cache=builder.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);

                        }

                    });

这个问题将得到解决。 这是一种有线的,但我想这是它是什么:)



文章来源: Guava CacheBuilder removal listener