0

我已经搜索了解决方案,因为其他问题也已发布java.lang.NullPointerExcpetion。但我无法找到我的问题。我正在使用 Ehcache 3,并且我已经实例化了一个缓存,它将数据放入缓存中。

作为缓存工作的类是:

import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.PersistentCacheManager;
import org.ehcache.config.ResourceType;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.expiry.Duration;
import org.ehcache.expiry.Expirations;

import javax.ejb.Stateless;
import javax.enterprise.inject.spi.CDI;
import java.io.File;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;


public class CacheHelper {

    private CacheManager cacheManager;

    private Cache<String,GenericClassForMap> mapPerson;


    private static Timer timer;

    public CacheHelper() {
        timer = new Timer();
        TimerTask task = new Helper();

        timer.schedule(task, 2, 5000);

    }

    //initialziing cache
    public void putInCacheFromDb() {
        System.getProperties().setProperty("java -Dnet.sf.ehcache.use.classic.lru", "true");
        cacheManager= CacheManagerBuilder
                .newCacheManagerBuilder().build();
        cacheManager.init();

        //for map
        mapPerson = cacheManager
                .createCache("cacheOfmap", CacheConfigurationBuilder
                        .newCacheConfigurationBuilder(
                                String.class,GenericClassForMap.class,
                                ResourcePoolsBuilder.heap(100000)).withExpiry(Expirations.timeToLiveExpiration(Duration.of(60000,
                                TimeUnit.SECONDS))));
        Map<Integer,Person> mp=new HashMap<>();
        mp.put(1,new Person(1,"om"));

        mapPerson.put(CACHE_MAP_PARAMETER,new GenericClassForMap(mp));

    }

    //method to clear the cache
    public void clearAllCache(){
        System.out.println("cache is being cleared........");
          cacheManager.close();
      }

}

当我运行程序时,数据被插入缓存并打印为:

 coming from map
[Person{id=1, name='om'}]

我正在为缓存设置计时器,并且需要在 15 秒内刷新缓存。所以,我尝试使用 Helper.java 类作为,

import com.cache.cachemanager.CacheHelper;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;


public class Helper extends TimerTask
{
    public static int i = 0;

    public void run()
    {
        System.out.println("Timer ran " + ++i);

        if(i==15){
            try {

                Thread.sleep(10000);
                System.out.println("system is sleeping");
                CacheHelper cacheHelper=new CacheHelper();
                cacheHelper.clearAllCache();
               cacheHelper.putInCacheFromDb();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


        }
    }
}

我在以下位置收到空指针异常:

system is sleeping
 cache is being cleared........
Exception in thread "Timer-6" java.lang.NullPointerException
   at com.cache.cachemanager.CacheHelper.clearAllCache(CacheHelper.java:309)
  at com.cache.timer.Helper.run(Helper.java:25)

我试图调试程序,我看到空指针异常来自:

 cacheManager.close();

我的缓存管理器为空。但是当我尝试从 API 请求中清除缓存时,它能够清除缓存。我没有使用 spring 框架。为什么我cacheManager是空的,但通过 API 调用时很容易将其删除,例如:

http://localhost:8080/myresource/clearCache,我的缓存很容易被清除。

cache is being cleared........
11:19:31,154 INFO  [org.ehcache.core.EhcacheManager] (default task-8) Cache 'cacheOfmap' removed from EhcacheManager.
4

1 回答 1

1

在调用您的clearAllCache方法之前,您创建了一个new CacheHelper(). 因此,cacheManager这个实例的属性永远不会被初始化(你只在putInCacheFromDb方法中初始化它)。
我猜当你通过 API 调用它时,你有一个 bean/singleton 实例被调用来填充你的缓存,然后永远不会被破坏。所以必须使用这个实例。

编辑:回答为什么cacheManager在构造函数中初始化的问题。
您当前的代码运行如下:

    // CacheHelper constructor is called to initialize a new CacheHelper
    // => cacheManager attribute is not initialized
    CacheHelper cacheHelper = new CacheHelper();
    // This method will call cacheManager.close().
    // => cacheManager is currently null => NullPointerException
    cacheHelper.clearAllCache();
    // This method will initialize the cacheManager attribute
    // => Too late the Exception already occured
    // => So, need to initialize cacheManager attribute before calling clearAllCache()
    // => the constructor is the best place to do this here.
    cacheHelper.putInCacheFromDb();
于 2019-09-10T05:53:38.410 回答