Mar*_*gen 1 java caching guava
我最近开始玩LoadingCache类,我得到一些意想不到的行为.我现在知道解决方案,但我发布了这个问题,以便其他人可以从中学习.
基本上,我在缓存中为某个键设置了一个非空值.关键是值在文件中的位置,并使用CacheLoader.load()方法,可以从文件中读取值.目前,LoadCache由单个线程使用.
当我运行我的应用程序时,将使用以前用于插入非空值的键的null值调用删除通知侦听器.我知道这是因为我使用assert语句检查进入缓存的所有值都不为null(这不应该发生).我也可以看到这个,因为我在CacheLoader.load()调用的方法中打印了密钥:CacheLoader.load()是唯一可以调用打印密钥的方法的方法.此外,此方法不能返回空值.
如果我做错了什么,有人可以告诉我,我会非常感激.
以下是我对加载缓存的定义.
private LoadingCache<Long,T> gcache( ) {
@SuppressWarnings( Constants.UNCHECKED )
final CacheLoader<Long,T> loader =
new CacheLoader<Long,T>() {
public T load(Long key) {
// This following method _did_ print the key for which
// the RemovalNotification listener returns a null value.
// See output further on.
return getElement( key );
}
};
@SuppressWarnings( Constants.UNCHECKED )
final RemovalListener<Long,T> listener
= new RemovalListener<Long,T>( ) {
@Override
public void onRemoval( RemovalNotification<Long,T> notification ) {
final T value = notification.getValue( );
////////////////////////////////////////////////////////////////////////////
if (value == null) {
System.out.println( "????: " + notification.getKey( ) );
}
assert( value != null);
////////////////////////////////////////////////////////////////////////////
if (!value.immutable( )) {
put( notification.getKey( ), value );
}
}
};
@SuppressWarnings( Constants.UNCHECKED )
final LoadingCache<Long, T> gcache
= CacheBuilder.newBuilder( )
.softValues( )
.removalListener( listener )
.build( loader );
return gcache;
}
private T getElement( long pos ) {
// Critical section, but at the moment there's only one thread.
enter( );
seek( pos );
final T creation = inflator.inflate( this );
///////////////////////////////////////////////////////////////////////
System.out.println( "getElement: pos = " + pos );
assert( creation != null );
///////////////////////////////////////////////////////////////////////
leave( );
return creation;
}
Run Code Online (Sandbox Code Playgroud)
一些输出:
[ cut ]
getElement: pos = 362848
[ cut ]
????: 362848
Run Code Online (Sandbox Code Playgroud)
在问号之后我得到了无法控制的输出量,并且JVM很难停止.在我终止申请之前,我必须多次按键.(当然kill也可以做到,但键盘稍快一点.)
我只是猜测:在RemovalNotification它的javadoc 读取
删除单个条目的通知.如果密钥和/或值已经被垃圾收集,则它们可以为null.
而你正在使用softValues().当值得到GC时,整个条目将从缓存中删除,并且密钥也可能被收集.