谈谈Java引用和Threadlocal的那些事

  

1背景
某一天在某一个群里面的某个群友突然提出了一个问题:“threadlocal的关键是弱引用,那么在threadlocal.get()的时候,发生GC之后,关键是否是零?“屏幕前的你可以好好的想想这个问题,在这里我先卖个关子,先讲讲Java中引用和threadlocal的那些事。

  Java中

2的引用
对于很多Java初学者来说,会把引用和对象给搞混淆。下面有一段代码,

  
 <代码>用户zhangsan=新用户(“zhangsan”, 24);  
  

这里先提个问题zhangsan到底是引用还是对象呢?很多人会认为zhangsan是个对象,如果你也是这样认为的话那么再看一下下面一段代码

  
 <代码>用户zhangsan;
  zhangsan=新用户(“zhangsan”, 24);  
  

这段代码和开始的代码其实执行效果是一致的,这段代码的第一行用户zhangsan定义了zhangsan,那你认为zhangsan还是对象吗?如果你还认为的话,那么这个对象应该是什么呢?的确,zhangsan其实只是一个引用,对JVM内存划分熟悉的同学应该熟悉下面的图片:
谈谈Java引用和Threadlocal的那些事”> <br/>是栈中分配的一个引用,而新用户(“zhangsan   

我们一般所说的引用其实都是代指的强引用,在JDK1.2之后引用不止这一种,一般来说分为四种:强引,用软引,用弱引,用虚引用。而接下来我会一一介绍这四种引用。

  

2.1强引用
上面我们说过了用户zhangsan=新用户(“zhangsan", 24);这种就是强引用,有点类似C的指针。对强引用他的特点有下面几个:

  

强引用可以直接访问目标对象。
只要这个对象被强引用所关联,那么垃圾回收器都不会回收,那怕是抛出伯父异常。
容易导致内存泄漏。
2.2软引用
在Java中使用SoftReference帮助我们定义软引用。其构造方法有两个:

  SoftReference (T
 <代码>公共referent);
  公共SoftReference (T referent ReferenceQueue<?超级T>问); 
  

两个构造方法相似,第二个比第一个多了一个引用队列,在构造方法中的第一个参数就是我们的实际被指向的对象,这里用新建一个SoftReference来替代我们上面强引用的等号。下面是构造软引用的例子:

  
 <代码> softZhangsan=new SoftReference(新用户(“zhangsan”, 24));  
  

2.2.1软引用有什么用?
如果某个对象他只被软引用所指向,那么他将会在内存要溢出的时候被回收,也就是当我们要出现伯父的时候,如果回收了一波内存还不够,这才抛出伯父,弱引用回收的时候如果设置了引用队列,那么这个软引用还会进一次引用队列,但是引用所指向的对象已经被回收。这里要和下面的弱引用区分开来,弱引用是只要有垃圾回收,那么他所指向的对象就会被回收。下面是一个代码例子:

  
 <代码>公共静态void main (String [] args) {
  ReferenceQueuereferenceQueue=new referenceQueue ();
  SoftReference SoftReference=new SoftReference(新用户(“zhangsan”, 24), referenceQueue);//手动触发GC
  system . gc ();
  thread . sleep (1000);
  system . out。println(“手动触发GC:“+ softReference.get ());
  system . out。println(“手动触发的队列:“+ referenceQueue.poll ());//通过堆内存不足触发GC
  makeHeapNotEnough ();
  system . out。println(“通过堆内存不足触发GC:”+ softReference.get ());
  system . out。println(“通过堆内存不足触发GC:”+ referenceQueue.poll ());
  }
  
  私有静态孔隙makeHeapNotEnough () {
  SoftReference SoftReference=new SoftReference(新字节(1024 * 1024 * 5));
  byte[]字节=new字节(1024 * 1024 * 5);
  }
  输出:
  手动触发GC:用户{name=' zhangsan,=24岁}
  手动触发的队列:零
  通过堆内存不足触发GC: null
  通过堆内存不足触发GC: java.lang.ref.SoftReference@4b85612c  
  

通过-Xmx10m设置我们堆内存大小为10,方便构造堆内存不足的情况。可以看见我们输出的情况我们手动调用system . gc并没有回收我们的软引用所指向的对象,只有在内存不足的情况下才能触发。

  2.2.2

软引用的应用
在SoftReference的医生中有这么一句话:

  
 <代码>软引用通常用于实现高速缓存
   
  

也就是说软引用经常用来实现内存敏感的高速缓存。怎么理解这句话呢?我们知道软引用他只会在内存不足的时候才触发,不会像强引用那用容易内存溢出,我们可以用其实现高速缓存,一方面内存不足的时候可以回收,一方面也不会频繁回收。在高速本地缓存咖啡因中实现了软引用的缓存,当需要缓存淘汰的时候,如果是只有软引用指向那么久会被回收。

谈谈Java引用和Threadlocal的那些事