Java中的引用
java中的引用分为四种,分别是强引用、软引用、弱引用、虚引用。四种引用的区别不同如下:
类型 | 解释 |
强引用(Strong Reference) |
强引用在程序代码中普遍存在,类似Object obj = new Object(),这类引用垃圾收集器永远不会回收掉被引用的对 象。 |
软引用(Soft Reference) |
软引用用来描述还有用但非必需的对象。在系统将要发生内存溢出之前,将会把这些对象列进回收范围之中进行第二次 回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。简单来说就是当JVM内存足够时,这类对象就不会被 回收,如果内存不足时,这类对象就会被回收。 |
弱引用(Weak Reference) | 弱引用也用来描述非必需的对象,但是它的强度比软引用更弱一些,这类对象在每次gc时都会被回收 |
虚引用 |
虚引用是最弱的一种引用关系,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用 来取得一个对象实例。设置虚引用的唯一目的就是能在这个对象被回收时收到一个系统通知。 |
1 package demo.reference; 2 3 import com.alibaba.fastjson.JSON; 4 import demo.reference.vo.User; 5 6 import java.lang.ref.SoftReference; 7 import java.lang.ref.WeakReference; 8 9 /** 10 * @Author: lianshuaibing 11 * @Date: 2020/2/12 3:46 下午 12 */ 13 public class ReferenceDemo { 14 15 public static void main(String[] args) { 16 //强引用 17 User user = new User("Dog", 10); 18 //软引用 19 SoftReference<User> softReference = new SoftReference<>(user); 20 //去掉强引用 21 user = null; 22 //垃圾器进行垃圾回收 23 System.gc(); 24 //结果:{"age":10,"name":"Dog"} 25 System.out.println(JSON.toJSONString(softReference.get())); 26 27 User user1 = new User("Cat", 11); 28 //弱引用 29 WeakReference<User> weakReference = new WeakReference<>(user1); 30 //去掉弱引用 31 user1 = null; 32 //gc操作 33 System.gc(); 34 //结果:null 35 System.out.println(JSON.toJSONString(weakReference)); 36 } 37 }
我们可以通过软引用和弱引用来提升JVM的效率。
比如说一个博客,为了提升性能,用户在点击博文时,如果这篇博文有缓存,这样其它用户在点击博文时就会直接从内存中加载,而不用再走数据库,这样能降低响应时间。首先我们定义一个Content类来封装博文内容,在其中可以包含文章的ID,文章内容、作者等信息。这是我们可以定义一个HashMap<String, SoftReference<Content>>对象来保存缓存内容,其中键是String类型,为文章ID,值为Content的软引用,随后当用户点击某个ID时,根据ID去HashMap里去找,如果找到且Content内容不为空就直接返回做展示动作,如果找不到或找到的content内容为空,再去数据库加载,同时缓存到HashMap中,注意,显示后需要删除Content的强引用,从而保证Content只有一个软引用。我们看一下这样使用有什么好处,假设我们有1G的空间,缓存了10000篇文章,那么这一万篇文章,在内存空间上只有软引用,没有强引用,如果内存空间足够时,那么我们可以通过缓存来提升性能;但万一内存不够时我们可以依次释放这10000篇文章所占的内存,而释放时不会影响业务流程,最多就是影响性能。对比一下如果我们使用强引用来做缓存,会有什么后果,因为我们不知道什么时候该撤销在Content上的强引用,所以说我们找不到一个合适的机会来释放缓存,而且我们在引入一套清空缓存的机制,那就属于额外工作了。就没有想软引用这么直接了。