>  기사  >  Java  >  Java 클래스 라이브러리-Guava-cache

Java 클래스 라이브러리-Guava-cache

黄舟
黄舟원래의
2017-01-19 13:14:351317검색

캐싱은 일상적인 개발에서 성능 문제를 해결하는 데 필수적인 방법입니다. 간단히 말해서, 캐시는 시스템 성능을 향상시키기 위해 열어둔 메모리 공간입니다.

캐싱은 다음과 같은 많은 시스템과 아키텍처에서 널리 사용됩니다.

1. CPU 캐시

2. 운영 체제 캐시

3. 로컬 캐시

4. 분산 캐시

5. HTTP 캐시

6. 데이터베이스 캐시

잠깐, 컴퓨터나 네트워크 분야에서는 그렇다고 할 수 있죠. , 캐싱은 어디에나 있습니다. 하드웨어 성능이 동일하지 않은 한 네트워크 전송이 관련된 모든 곳에 캐시가 존재한다고 말할 수 있습니다.

Guava Cache는 스레드로부터 안전한 구현 메커니즘을 제공하는 전체 메모리 로컬 캐시 구현입니다. 전반적으로 Guava 캐시는 로컬 캐싱에 가장 적합한 선택입니다. 사용하기 쉽고 성능도 좋습니다.

Guava 캐시를 생성하는 방법은 두 가지가 있습니다.

1. 캐시로더

2. 콜백 콜백

이 두 가지 방법으로 생성하는 캐시는 동일합니다. 평소와 같이 맵을 캐시로 사용하는 것의 차이점은 두 메서드 모두 논리를 구현한다는 것입니다. 캐시에서 키 X의 값을 가져오고, 값이 캐시된 경우 캐시에 값을 반환하고, 캐시되지 않은 경우에는 메서드가 있습니다. 이 값을 얻으려면. 그러나 차이점은 캐시로더의 정의가 비교적 광범위하고 전체 캐시에 대해 정의된다는 점입니다. 키 값을 기준으로 값을 로드하는 통일된 방법이라고 볼 수 있습니다. 호출 가능 메소드는 더 유연하여 가져올 때

을 지정할 수 있습니다. 캐시로더 메소드 구현 예:

[code] @Test
    public void TestLoadingCache() throws Exception{
        LoadingCache<String,String> cahceBuilder=CacheBuilder
        .newBuilder()
        .build(new CacheLoader<String, String>(){
            @Override
            public String load(String key) throws Exception {        
                String strProValue="hello "+key+"!";                
                return strProValue;
            }

        });        

        System.out.println("jerry value:"+cahceBuilder.apply("jerry"));
        System.out.println("jerry value:"+cahceBuilder.get("jerry"));
        System.out.println("peida value:"+cahceBuilder.get("peida"));
        System.out.println("peida value:"+cahceBuilder.apply("peida"));
        System.out.println("lisa value:"+cahceBuilder.apply("lisa"));
        cahceBuilder.put("harry", "ssdded");
        System.out.println("harry value:"+cahceBuilder.get("harry"));
    }

콜 가능 콜백 구현:

[code] @Test
    public void testcallableCache()throws Exception{
        Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).build();  
        String resultVal = cache.get("jerry", new Callable<String>() {  
            public String call() {  
                String strProValue="hello "+"jerry"+"!";                
                return strProValue;
            }  
        });  
        System.out.println("jerry value : " + resultVal);

        resultVal = cache.get("peida", new Callable<String>() {  
            public String call() {  
                String strProValue="hello "+"peida"+"!";                
                return strProValue;
            }  
        });  
        System.out.println("peida value : " + resultVal);  
    }

  输出:
  jerry value : hello jerry!
  peida value : hello peida!

캐시 매개변수 설명:

재활용 매개변수:

1. 크기 설정: CacheBuilder.maximumSize(long) CacheBuilder.weigher(Weigher) CacheBuilder.maxumumWeigher(long)

2. 시간:expirAfterAccess(long, TimeUnit) 만료AfterWrite(long, TimeUnit)

3. 참조: CacheBuilder.weakKeys() CacheBuilder.weakValues() CacheBuilder.softValues()

4. 명시적 삭제: 무효화( 키) 무효화All( 키) 무효화All()

5. 리스너 삭제: CacheBuilder.removalListener(RemovalListener)



새로 고침 메커니즘:

1. LoadingCache.refresh(K ) 새 값을 생성할 때 이전 값이 계속 사용됩니다.

 2.CacheLoader.reload(K, V)는 새 값을 생성하는 과정에서 이전 값을 사용할 수 있도록 허용합니다.

 3. CacheBuilder.refreshAfterWrite(long, TimeUnit) 자동으로 캐시를 새로 고칩니다.

[code] /**
     * 不需要延迟处理(泛型的方式封装)
     * @return
     */
    public  <K , V> LoadingCache<K , V> cached(CacheLoader<K , V> cacheLoader) {
          LoadingCache<K , V> cache = CacheBuilder
          .newBuilder()
          .maximumSize(2)
          .weakKeys()
          .softValues()
          .refreshAfterWrite(120, TimeUnit.SECONDS)
          .expireAfterWrite(10, TimeUnit.MINUTES)        
          .removalListener(new RemovalListener<K, V>(){
            @Override
            public void onRemoval(RemovalNotification<K, V> rn) {
                System.out.println(rn.getKey()+"被移除");  

            }})
          .build(cacheLoader);
          return cache;
    }

    /**
     * 通过key获取value
     * 调用方式 commonCache.get(key) ; return String
     * @param key
     * @return
     * @throws Exception
     */

    public  LoadingCache<String , String> commonCache(final String key) throws Exception{
        LoadingCache<String , String> commonCache= cached(new CacheLoader<String , String>(){
                @Override
                public String load(String key) throws Exception {
                    return "hello "+key+"!";    
                }
          });
        return commonCache;
    }

    @Test
    public void testCache() throws Exception{
        LoadingCache<String , String> commonCache=commonCache("peida");
        System.out.println("peida:"+commonCache.get("peida"));
        commonCache.apply("harry");
        System.out.println("harry:"+commonCache.get("harry"));
        commonCache.apply("lisa");
        System.out.println("lisa:"+commonCache.get("lisa"));
    }
peida:hello peida!
harry:hello harry!
peida被移除
lisa:hello lisa!

일반 기반 호출 가능 캐시 구현:

[code]private static Cache<String, String> cacheFormCallable = null; 

    /**
     * 对需要延迟处理的可以采用这个机制;(泛型的方式封装)
     * @param <K>
     * @param <V>
     * @param key
     * @param callable
     * @return V
     * @throws Exception
     */
    public static <K,V> Cache<K , V> callableCached() throws Exception {
          Cache<K, V> cache = CacheBuilder
          .newBuilder()
          .maximumSize(10000)
          .expireAfterWrite(10, TimeUnit.MINUTES)
          .build();
          return cache;
    }

    private String getCallableCache(final String userName) {
           try {
             //Callable只有在缓存值不存在时,才会调用
             return cacheFormCallable.get(userName, new Callable<String>() {
                @Override
                public String call() throws Exception {
                    System.out.println(userName+" from db");
                    return "hello "+userName+"!";
               }
              });
           } catch (ExecutionException e) {
              e.printStackTrace();
              return null;
            } 
    }

    @Test
    public void testCallableCache() throws Exception{
         final String u1name = "peida";
         final String u2name = "jerry"; 
         final String u3name = "lisa"; 
         cacheFormCallable=callableCached();
         System.out.println("peida:"+getCallableCache(u1name));
         System.out.println("jerry:"+getCallableCache(u2name));
         System.out.println("lisa:"+getCallableCache(u3name));
         System.out.println("peida:"+getCallableCache(u1name));

    }

  输出:

peida from db
peida:hello peida!
jerry from db
jerry:hello jerry!
lisa from db
lisa:hello lisa!
peida:hello peida!

  说明:Callable只有在缓存值不存在时,才会调用,比如第二次调用getCallableCache(u1name)直接返回缓存中的值

  guava Cache数据移除:

  guava做cache时候数据的移除方式,在guava中数据的移除分为被动移除和主动移除两种。 

  被动移除数据的方式,guava默认提供了三种方式: 

  1.基于大小的移除:看字面意思就知道就是按照缓存的大小来移除,如果即将到达指定的大小,那就会把不常用的键值对从cache中移除。 

  定义的方式一般为 CacheBuilder.maximumSize(long),还有一种一种可以算权重的方法,个人认为实际使用中不太用到。就这个常用的来看有几个注意点, 

    其一,这个size指的是cache中的条目数,不是内存大小或是其他; 

    其二,并不是完全到了指定的size系统才开始移除不常用的数据的,而是接近这个size的时候系统就会开始做移除的动作; 

    其三,如果一个键值对已经从缓存中被移除了,你再次请求访问的时候,如果cachebuild是使用cacheloader方式的,那依然还是会从cacheloader中再取一次值,如果这样还没有,就会抛出异常 

  2.基于时间的移除:guava提供了两个基于时间移除的方法 

    expireAfterAccess(long, TimeUnit) 这个方法是根据某个键值对最后一次访问之后多少时间后移除 

    expireAfterWrite(long, TimeUnit) 这个方法是根据某个键值对被创建或值被替换后多少时间移除 

  3.基于引用的移除: 

  这种移除方式主要是基于java的垃圾回收机制,根据键或者值的引用关系决定移除 

  主动移除数据方式,主动移除有三种方法: 

  1.单独移除用 Cache.invalidate(key) 

  2.批量移除用 Cache.invalidateAll(keys) 

  3.移除所有用 Cache.invalidateAll() 

  如果需要在移除数据的时候有所动作还可以定义Removal Listener,但是有点需要注意的是默认Removal Listener中的行为是和移除动作同步执行的,如果需要改成异步形式,可以考虑使用RemovalListeners.asynchronous(RemovalListener, Executor)

以上就是Java-类库-Guava-cache的内容,更多相关内容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.