java ref 应用类型_Java四种引用类型
Java四種引用類型
在java中,類型就分為兩種,基本類型和引用類型或自定義類型。
引用類型又分為四種:
強(qiáng)引用 StrongReference
軟引用 SoftReference
若引用 WeakReference
虛引用 PhantomReference
劃分這些類型的目的是:是為了更靈活的管理對(duì)象的生命周期,讓垃圾器在最合適的時(shí)間適合回收對(duì)象,常見使用的場(chǎng)景是在緩存的實(shí)現(xiàn),比如elasticsearch在載入數(shù)據(jù)到緩存時(shí),可以選擇SoftReference作為緩存的生命周期,在對(duì)象池組件common-pool中也利用到SoftReference管理對(duì)象池的對(duì)象生命周期。雖然,我們?cè)趯?shí)際業(yè)務(wù)中很少有用到這些知識(shí),但是很有必要了解到這些,去幫助我們?nèi)プ鲂┏绦蛐阅軆?yōu)化。
強(qiáng)引用
強(qiáng)引用就是直接引用對(duì)象比如下面這樣,我們?cè)诰帉懗绦驎r(shí),用到的大多都是強(qiáng)引用
StringBuffer b1 = new StringBuffer("hello world");
強(qiáng)引用對(duì)象,當(dāng)垃圾回收進(jìn)行時(shí),不會(huì)被回收,及時(shí)通過b1 = null;釋放引用,在資源充足時(shí),也不會(huì)被垃圾回收立刻回收。如果內(nèi)存吃緊,Java虛擬機(jī)會(huì)拋出OutOfMemoryError錯(cuò)誤,使程序異常終止,不會(huì)靠隨意回收具有強(qiáng)引用的對(duì)象來解決內(nèi)存不足的問題。
軟引用
SoftReference softReference = new SoftReference(new StringBuffer("hello world"));
System.gc();
System.out.print(softReference.get()); // 只有當(dāng)內(nèi)存吃緊時(shí),發(fā)生gc后,會(huì)報(bào)Exception in thread "main" java.lang.NullPointerException,
軟引用的生命周期會(huì)比強(qiáng)引用弱點(diǎn),在內(nèi)存空間足夠時(shí),垃圾回收器就不會(huì)回收它;如果內(nèi)存空間不足了,就會(huì)回收這些對(duì)象的內(nèi)存。只要垃圾回收器沒有回收它,該對(duì)象就可以被程序使用。軟引用可用來實(shí)現(xiàn)內(nèi)存敏感的高速緩存。
它也經(jīng)常和ReferenceQueue配合使用,如果gc在回收掉引用對(duì)象后,會(huì)把保存引用對(duì)象的softReference送入隊(duì)列,這時(shí)可以通過下面這行代碼判斷是否被回收。
// 創(chuàng)建softReference并提供給注冊(cè)隊(duì)列
ReferenceQueue referenceQueue = new ReferenceQueue();
SoftReference softReference = new SoftReference(new StringBuffer("hello world"),referenceQueue);
// 判斷入隊(duì)列來判斷是否被回收,或直接判斷softReference.get() == null
softReference.get() == null || softReference.enqueue()
另外也可以手動(dòng)清除這些保存引用對(duì)象的reference對(duì)象
Reference ref;
while ((ref = referenceQueue.poll()) != null) {
// poll出即清除,也不必手動(dòng)清除,等待gc清除
}
使用案列:common-pool2的SoftReferenceObjectPool,用于實(shí)現(xiàn)一種可以隨著需要而增長(zhǎng)的池對(duì)象管理,當(dāng)gc時(shí)可以清除空閑的實(shí)例。
下面是common-pool2的部分代碼,具體可以參照其里面的SoftReferenceObjectPool類
@Override
public synchronized void addObject() throws Exception {
assertOpen();
if (factory == null) {
throw new IllegalStateException(
"Cannot add objects without a factory.");
}
T obj = factory.makeObject().getObject();
createCount++;
// Create and register with the queue
PooledSoftReference ref = new PooledSoftReference(
new SoftReference(obj, refQueue));
allReferences.add(ref);
boolean success = true;
if (!factory.validateObject(ref)) {
success = false;
} else {
factory.passivateObject(ref);
}
boolean shouldDestroy = !success;
if (success) {
idleReferences.add(ref);
notifyAll(); // numActive has changed
}
if (shouldDestroy) {
try {
destroy(ref);
} catch (Exception e) {
// ignored
}
}
@Override
public synchronized void returnObject(T obj) throws Exception {
boolean success = !isClosed();
final PooledSoftReference ref = findReference(obj);
if (ref == null) {
throw new IllegalStateException(
"Returned object not currently part of this pool");
}
if (factory != null) {
if (!factory.validateObject(ref)) {
success = false;
} else {
try {
factory.passivateObject(ref);
} catch (Exception e) {
success = false;
}
}
}
boolean shouldDestroy = !success;
numActive--;
if (success) {
// Deallocate and add to the idle instance pool
ref.deallocate();
idleReferences.add(ref);
}
notifyAll(); // numActive has changed
if (shouldDestroy && factory != null) {
try {
destroy(ref);
} catch (Exception e) {
// ignored
}
}
}
弱引用
WeakReference weakReference = new WeakReference(new StringBuffer("hello world"));
WeakReference weakReference2 = new WeakReference(new StringBuffer("hello world"));
System.out.print(weakReference.get()); // hello world
StringBuffer buffer = weakReference2.get();
System.gc();
System.out.print(weakReference.get()); // Exception in thread "main" java.lang.NullPointerException
System.out.print(weakReference2.get()); // hello world
弱引用會(huì)在發(fā)生gc時(shí),沒有對(duì)象在去引用時(shí)會(huì)被立刻被回收,不管內(nèi)存是否充裕。
使用案列:WeakHashMap
虛引用
ReferenceQueue stringBufferReferenceQueue = new ReferenceQueue();
PhantomReference phantomReference = new PhantomReference(new StringBuffer("hello world"), stringBufferReferenceQueue);
System.out.print(phantomReference.get());Exception in thread "main" java.lang.NullPointerException
虛引用,不顧是否被垃圾回收,都不可以拿到真正的引用對(duì)象。一般用法是
程序可以通過判斷引用隊(duì)列中是否已經(jīng)加入了虛引用,來了解被引用的對(duì)象是否將要被垃圾回收。如果程序發(fā)現(xiàn)某個(gè)虛引用已經(jīng)被加入到引用隊(duì)列,那么就可以在所引用的對(duì)象的內(nèi)存被回收之前采取必要的行動(dòng)。
具體Demo代碼請(qǐng)參照:ReferenceDemo
總結(jié)
以上是生活随笔為你收集整理的java ref 应用类型_Java四种引用类型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java网络编程与分布式计算_Java网
- 下一篇: java string 内存占用_JVM