1. 程式人生 > 程式設計 >ThreadLocal前奏:我理解的java四種引用型別

ThreadLocal前奏:我理解的java四種引用型別

前言

為了理解ThreadLocal,掌握引用的概念是非常有必要的。

引用與物件

java中我們通過一個引用指向記憶體中物件。

//建立一個引用,引用可以獨立存在,並不一定需要與一個物件關聯
User user;
user =  new User();
複製程式碼

user是引用, 通過‘=’指向了記憶體中的物件。

四種引用

JDK1.2後,根據對物件的引用強度不同,將引用分為4種型別。

強引用:

平時使用最多,最普遍的引用。

User user;
user =  new User();//強引用
複製程式碼
  • user就是強引用
  • 堆中的User物件例項,就是“被應用”;

只要user 指向 User物件。User物件就不會被回收。

user = null;斷開了引用,User物件不可達,會被回收。
複製程式碼
軟引用:

我們可以通過SoftReference來定義一個軟引用

SoftReference<User> softRef=new SoftReference<User>(new User());//軟引用
複製程式碼
  • 如果一個物件只有軟引用,記憶體足夠時,GC時不回收他。如果內容空間不足時,就會回收被軟引用指向的物件記憶體。
  • 只要沒有別回收,還可以使用

解釋下:物件只有軟引用 物件有兩種引用的情況

User user  = new User();//強引用
SoftReference<User> softRef=new
SoftReference<User>(user);//軟引用 複製程式碼

物件只有軟引用情況

SoftReference<User> softRef=new SoftReference<User>(new User());//軟引用
複製程式碼

User user  = new User();//強引用
SoftReference<User> softRef=new SoftReference<User>(user);//軟引用
user = null;//斷開了強引用。 此時只有軟引用。
複製程式碼

軟引用可與引用佇列(ReferenceQueue)聯合使用,在建立軟引用時,關聯ReferenceQueue。如果軟引用引用的物件被回收時,Java虛擬機器器會把這個軟引用加入到與之關聯的引用佇列中。

軟引用可用作記憶體敏感的快取記憶體。

弱引用:

可以通過WeakReference來定義一個弱引用

WeakReference<> weak = new WeakReference<>(new User());//定義一個軟引用指向堆內User物件
複製程式碼
  • 如果物件只有弱引用,GC時,不管記憶體是否足夠。都會回收,弱引用指向的物件。

弱引用也可與引用佇列(ReferenceQueue)聯合使用,在建立弱引用時,關聯ReferenceQueue。如果弱引用引用的物件被回收時,Java虛擬機器器會把這個弱引用加入到與之關聯的引用佇列中。

ThreadLocal 中使用到了弱引用。

虛引用:

虛引用是最弱的引用,弱到,不能用弱引用訪問到物件。

可以通過PhantomReference來定義一個虛引用。

虛引用,主要用來跟蹤物件被垃圾回收器回收的活動。

虛引用必須與引用佇列(ReferenceQueue)一起使用,當垃圾回收器準備回收一個物件時,如果發現它還有虛引用,就會在回收物件的記憶體之前,把這個虛引用加入到與之 關聯的引用佇列中。我們可以根據引用是否在佇列中,來判斷物件的回收活動。

為什麼需要不同的引用型別

我們看出引用強度的不同,物件的生命週期不同,垃圾回收策略豐富,有利於更好的管理物件記憶體。


總結:

  • 引用與物件的生命週期相關。
  • 物件可以被多種型別的,多個引用指向,但只要有一個強引用。垃圾回收器不回收。

關鍵時理解: 一個物件,可以被多種型別引用同時指向,強度最高的決定他的生命週期

注意:這裡的記憶體應該是指“堆記憶體”,並且區分引用型別基本型別

//String user ="user";//
String user = new String("user");
SoftReference<String> softRef=new SoftReference<String>(user);
WeakReference<String> weak = new WeakReference<String>(user);
user=null;
System.out.println(softRef.get());
System.gc();
System.out.println(weak.get());
複製程式碼