1

作者: Teemo_fca4 | 来源:发表于2022-09-22 10:15 被阅读0次
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    

    package com.example.springboottest.guava_cache;

    import com.google.common.base.MoreObjects;

    /***************************************

    • @author:Alex Wang

    • @Date:2017/11/18

    • QQ: 532500648

    • QQ群:463962286
      ***************************************/
      public class Employee
      {
      private final String name;
      private final String dept;
      private final String empID;
      private final byte[] data = new byte[1024 * 1024];

      public Employee(String name, String dept, String empID)
      {
      this.name = name;
      this.dept = dept;
      this.empID = empID;
      }

      public String getName()
      {
      return name;
      }

      public String getDept()
      {
      return dept;
      }

      public String getEmpID()
      {
      return empID;
      }

      @Override
      public String toString()
      {
      return MoreObjects.toStringHelper(this)
      .add("Name", this.getName()).add("Department", getDept())
      .add("EmployeeID", this.getEmpID()).toString();
      }

      @Override
      protected void finalize() throws Throwable
      {
      System.out.println("The name " + getName() + " will be GC.");
      }
      }

    package com.example.springboottest.guava_cache;

    import com.google.common.cache.CacheBuilder;
    import com.google.common.cache.CacheLoader;
    import com.google.common.cache.LoadingCache;
    import com.google.common.cache.Weigher;

    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.TimeUnit;

    public class _1_CacheLoaderBasicTest {

    public static void main(String[] args) throws Exception{
    

    // test1();
    // test2();
    // test3();
    // test4();
    test5();
    }

    /**测试软引用在缓存中被过期
     * 需要设置堆内存信息
     * -Xms64M -Xmx64M -XX:+PrintGCDetails
     * @throws Exception
     */
    private static void test5() throws Exception{
        LoadingCache<String, Employee> cache = CacheBuilder.newBuilder()
                .expireAfterWrite(200, TimeUnit.SECONDS)
                .softValues()//只能对values 做软引用处理
                .build(createCacheLoader2());
        int i = 0;
        //Employee 内部会有一个1M的数组,所以一个Employee对象 至少占1M空间
        //由于软引用在内存快不足的时候会被回收 所以这里运行结果 可以创建很多对象 不止64个
        //todo 但是考虑到软引用的性能影响 一般我们在在缓存中设置size来限制缓存所占内存的总大小 而不是使用软引用来
        for (; ; )  {
            String key = "Alex" + i;
            cache.put(key, new Employee(key, key, key));
    

    // cache.get(key);
    // System.gc();
    System.out.println("The Employee [" + (i++) + "] is store into cache.");
    TimeUnit.MILLISECONDS.sleep(200);
    }
    }

    //测试弱引用(weakReference) 在缓存中被过期
    public static void test4() throws InterruptedException  {
        LoadingCache<String, Employee> cache = CacheBuilder.newBuilder()
                .expireAfterWrite(2, TimeUnit.SECONDS)
                .weakValues()
                .weakKeys()
                .build(createCacheLoader2());
        cache.getUnchecked("Alex");
        cache.getUnchecked("Guava");
    
        //active method
        //Thread Active design pattern
        System.gc();
        TimeUnit.MILLISECONDS.sleep(100);
        //weak:弱引用 每次gc的时候 都会将其回收, 所以这里从缓存中拿不到数据了
        System.out.println(cache.getIfPresent("Alex"));
    }
    
    //测试Write的expire模式下的缓存存活情况
    private static void test3() throws Exception {
        LoadingCache<String, Employee> cache = CacheBuilder.newBuilder()
                //expireAfterWrite,write:包括写(write)和更新(update) 不包括读(read)
                .expireAfterWrite(2, TimeUnit.SECONDS)
                .build(createCacheLoader2());
    
        cache.getUnchecked("Guava");
    
        TimeUnit.SECONDS.sleep(1);
        Employee guava = cache.getIfPresent("Guava");
        System.out.println(guava);//1s后guava 此时存活
        TimeUnit.MILLISECONDS.sleep(900);
        guava = cache.getIfPresent("Guava");
        System.out.println(guava);//1.90s guava 此时依然存活
    
        TimeUnit.SECONDS.sleep(1);
        guava = cache.getIfPresent("Guava");
        System.out.println(guava);//2.99s guava 此时不存活
    }
    
    //测试Access的expire模式下的缓存存活情况
    private static void test2() throws Exception{
        LoadingCache<String, Employee> cache = CacheBuilder.newBuilder()
                //expireAfterAccess,access:包括读(read),写(write),改(update),都会续长缓存的存活期
                .expireAfterAccess(2, TimeUnit.SECONDS)
                .build(createCacheLoader2());
        cache.getUnchecked("Alex");
    
        TimeUnit.SECONDS.sleep(3);
        Employee alex =  cache.getIfPresent("Alex");//睡眠了 3s 此时缓存获取不到数据
        System.out.println(alex);
    
        cache.getUnchecked("Guava");
    
        TimeUnit.SECONDS.sleep(1);
        Employee employee = cache.getIfPresent("Guava");//此时Guava存在
        System.out.println(employee);
    
        TimeUnit.SECONDS.sleep(1);
        employee = cache.getIfPresent("Guava");//再次获取Guava 依然存在
        System.out.println(employee);
    
        TimeUnit.SECONDS.sleep(1);
        employee = cache.getIfPresent("Guava");//再次获取Guava 依然存在
        System.out.println(employee);
    }
    
    //测试基础用法
    public static void test1() throws ExecutionException, InterruptedException {
        //创建一个缓存容器对象 其最大容量是3,容器内元素存放30ms就过期
        LoadingCache<String, Employee> cache = CacheBuilder.newBuilder()
                .maximumSize(3)
                .expireAfterAccess(30, TimeUnit.MILLISECONDS)
                .build(createCacheLoader());
        //#################################### 测试30ms时间过期 ####################################
    

    // System.out.println(cache.get("Alex").getName());
    // TimeUnit.MILLISECONDS.sleep(31);
    // System.out.println(cache.get("Alex").getName());
    //测试到达容量之后 LRU过期
    //#################################### 测试到达size之后被LRU过期(过期策略:size) ####################################
    // System.out.println(cache.get("Alex").getName());
    // System.out.println(cache.get("allen").getName());
    // System.out.println(cache.get("tom").getName());
    // System.out.println(cache.get("amy").getName());//此时Alex被过期调,再拿Alex的话会从DB中拿
    // System.out.println(cache.size());
    // System.out.println(cache.get("Alex").getName());
    // System.out.println();
    //#################################### 测试到达weight之后被LRU过期(过期策略:自定义) ####################################

        //设置一个称重器 称重的方式是:对象的重量weight = name的长度 + empId的长度 + Dept的长度
        Weigher<String, Employee> weigher = (key, employee) ->
                employee.getName().length() + employee.getEmpID().length() + employee.getDept().length();
    
        //设置缓存重量限制为45
        LoadingCache<String, Employee> cache2 = CacheBuilder.newBuilder()
                .maximumWeight(45)
                .concurrencyLevel(1)
                .weigher(weigher)
                .build(createCacheLoader());
    
        cache2.get("Gavin");//缓存重量:15
        cache2.get("Kevin");//缓存重量:30
        cache2.get("Allen");//缓存重量:45
        cache2.get("Jason");//重量已经达到45,此时Gavin被过期
    
        Employee employee = cache2.getIfPresent("Gavin");//此时再去缓存中拿Gavin 是拿不到的
        System.out.println(employee);
    
    
        //#################################### LoadingCache 的一些api ####################################
    

    // 从LoadingCache中拿数据,如果拿不到,会去从DB中拿,
    // cache.get("aa");
    // 与get()方法的区别是这里不需要显式捕获异常
    // cache.getUnchecked("aa");
    // 从缓存中拿key对应的数据,如果缓存中没有 就返回null,不会去从DB中拿
    // cache.getIfPresent("aa");

    }
    
    
    private static  CacheLoader<String, Employee> createCacheLoader() {
        return new CacheLoader<String, Employee>() {
            @Override
            public Employee load(String key) throws Exception {
    

    // 这里要注意:load的时候不能返回空, 那返回空了怎么办?很有可能命中不了
    // if (key.equals("aa")) return null;
    System.out.println("从数据库中拿数据: " + key);
    return new Employee(key, key, key);
    }
    };
    }

    private static CacheLoader<String, Employee> createCacheLoader2()  {
        //也可以使用from()来构建缓存
        return CacheLoader.from(key -> new Employee(key, key, key));
    }
    

    }

    相关文章

      网友评论

          本文标题:1

          本文链接:https://www.haomeiwen.com/subject/dqfnortx.html