Guava 源码分析(Cache 原理【二阶段】)(上)

简介: 在上文「Guava 源码分析(Cache 原理)」中分析了 Guava Cache 的相关原理。文末提到了回收机制、移除时间通知等内容,许多朋友也挺感兴趣,这次就这两个内容再来分析分析。在开始之前先补习下 Java 自带的两个特性,Guava 中都有具体的应用。

Java 中的引用


首先是 Java 中的引用


在之前分享过 JVM 是根据可达性分析算法找出需要回收的对象,判断对象的存活状态都和引用有关。


在 JDK1.2 之前这点设计的非常简单:一个对象的状态只有引用没被引用两种区别。


这样的划分对垃圾回收不是很友好,因为总有一些对象的状态处于这两之间。


因此 1.2 之后新增了四种状态用于更细粒度的划分引用关系:


  • 强引用(Strong Reference):这种对象最为常见,比如 **A a = new A();**这就是典型的强引用;这样的强引用关系是不能被垃圾回收的。


  • 软引用(Soft Reference):这样的引用表明一些有用但不是必要的对象,在将发生垃圾回收之前是需要将这样的对象再次回收。


  • 弱引用(Weak Reference):这是一种比软引用还弱的引用关系,也是存放非必须的对象。当垃圾回收时,无论当前内存是否足够,这样的对象都会被回收。


  • 虚引用(Phantom Reference):这是一种最弱的引用关系,甚至没法通过引用来获取对象,它唯一的作用就是在被回收时可以获得通知。


事件回调


事件回调其实是一种常见的设计模式,比如之前讲过的 Netty 就使用了这样的设计。


这里采用一个 demo,试下如下功能:


  • Caller 向 Notifier 提问。


  • 提问方式是异步,接着做其他事情。


  • Notifier 收到问题执行计算然后回调 Caller 告知结果。


在 Java 中利用接口来实现回调,所以需要定义一个接口:


public interface CallBackListener {
    /**
     * 回调通知函数
     * @param msg
     */
    void callBackNotify(String msg) ;
}


Caller 中调用 Notifier 执行提问,调用时将接口传递过去:


public class Caller {
    private final static Logger LOGGER = LoggerFactory.getLogger(Caller.class);
    private CallBackListener callBackListener ;
    private Notifier notifier ;
    private String question ;
    /**
     * 使用
     */
    public void call(){
        LOGGER.info("开始提问");
    //新建线程,达到异步效果 
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    notifier.execute(Caller.this,question);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        LOGGER.info("提问完毕,我去干其他事了");
    }
    //隐藏 getter/setter
}    


Notifier 收到提问,执行计算(耗时操作),最后做出响应(回调接口,告诉 Caller 结果)。


public class Notifier {
    private final static Logger LOGGER = LoggerFactory.getLogger(Notifier.class);
    public void execute(Caller caller, String msg) throws InterruptedException {
        LOGGER.info("收到消息=【{}】", msg);
        LOGGER.info("等待响应中。。。。。");
        TimeUnit.SECONDS.sleep(2);
        caller.getCallBackListener().callBackNotify("我在北京!");
    }
}


模拟执行:


public static void main(String[] args) {
        Notifier notifier = new Notifier() ;
        Caller caller = new Caller() ;
        caller.setNotifier(notifier) ;
        caller.setQuestion("你在哪儿!");
        caller.setCallBackListener(new CallBackListener() {
            @Override
            public void callBackNotify(String msg) {
                LOGGER.info("回复=【{}】" ,msg);
            }
        });
        caller.call();
    }


最后执行结果:


2018-07-15 19:52:11.105 [main] INFO  c.crossoverjie.guava.callback.Caller - 开始提问
2018-07-15 19:52:11.118 [main] INFO  c.crossoverjie.guava.callback.Caller - 提问完毕,我去干其他事了
2018-07-15 19:52:11.117 [Thread-0] INFO  c.c.guava.callback.Notifier - 收到消息=【你在哪儿!】
2018-07-15 19:52:11.121 [Thread-0] INFO  c.c.guava.callback.Notifier - 等待响应中。。。。。
2018-07-15 19:52:13.124 [Thread-0] INFO  com.crossoverjie.guava.callback.Main - 回复=【我在北京!】


这样一个模拟的异步事件回调就完成了。


相关文章
|
缓存 NoSQL Java
Java工具篇之Guava-cache内存缓存
常在业务系统中做开发,不会点高级知识点,有点不好意思了。在业务系统中,提高系统响应速度,提供系统高并发能力,其实方向很简单,三个方向,六个字而已: **缓存降级限流。** 当然这是在排除代码质量非常差的情况,如果代码质量很差,都是while循环和高内存占用,那么其实再怎么做都于事无补。除非你有一个马云爸爸,性能不够,机器来凑嘛。阿里云前来支持(1000台机器够了吗?)
1287 0
|
7月前
|
XML 存储 缓存
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache管理器的实战开发指南(修正篇)
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache管理器的实战开发指南(修正篇)
120 0
|
4月前
|
缓存 Java Spring
Java本地高性能缓存实践问题之Caffeine中设置刷新机制的问题如何解决
Java本地高性能缓存实践问题之Caffeine中设置刷新机制的问题如何解决
128 1
|
4月前
|
缓存 Java
Java本地高性能缓存实践问题之使用Caffeine的Cache接口来查找一个缓存元素的问题如何解决
Java本地高性能缓存实践问题之使用Caffeine的Cache接口来查找一个缓存元素的问题如何解决
|
7月前
|
存储 XML 缓存
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache功能的开发实战指南(一)
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache功能的开发实战指南
479 0
|
4月前
|
存储 缓存 监控
Java本地高性能缓存实践问题之Guava Cache被Caffeine所取代的问题如何解决
Java本地高性能缓存实践问题之Guava Cache被Caffeine所取代的问题如何解决
|
4月前
|
缓存 Java Spring
Java本地高性能缓存实践问题之的Caffeine设置刷新机制问题如何解决
Java本地高性能缓存实践问题之的Caffeine设置刷新机制问题如何解决
128 0
|
存储 设计模式 缓存
Java源码分析:Guava之不可变集合ImmutableMap的源码分析
Java源码分析:Guava之不可变集合ImmutableMap的源码分析
66 0
|
7月前
|
缓存 NoSQL Java
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache功能的开发实战指南(二)
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache功能的开发实战指南
160 0
|
存储 缓存 监控
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache抽象详解的核心原理探索
缓存的工作机制是先从缓存中读取数据,如果没有再从慢速设备上读取实际数据,并将数据存入缓存中。通常情况下,我们会将那些经常读取且不经常修改的数据或昂贵(CPU/IO)的且对于相同请求有相同计算结果的数据存储到缓存中。
197 1