亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java中的Reference類型用法說(shuō)明

 更新時(shí)間:2020年09月27日 10:03:43   作者:嘖嘖嘖嘖zezezeze  
這篇文章主要介紹了java中的Reference類型用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

本文簡(jiǎn)要總結(jié)java中的Reference類型。

最近在研讀jdk并發(fā)框架,其中AQS是重點(diǎn),由于我打破砂鍋問(wèn)到底的輕微強(qiáng)迫癥,google了AQS作者Doug Lea的論文原文[The java.util.concurrent Synchronizer Framework],有興趣的同學(xué)可以自行下載。其中談到設(shè)計(jì)同步框架的核心是選擇一個(gè)嚴(yán)格意義上的FIFO隊(duì)列,作為阻塞線程隊(duì)列并對(duì)其進(jìn)行維護(hù)。

對(duì)此主要由兩種選擇,一個(gè)是MCS鎖,另一個(gè)時(shí)CLH鎖。因?yàn)镃LH鎖比MCS對(duì)取消和超時(shí)的處理更方便,所以AQS就選擇將CLH鎖作為基礎(chǔ)對(duì)其進(jìn)行改進(jìn)。于是我又打算先弄懂什么是CLH鎖,在網(wǎng)上搜索了一圈之后找到很多人對(duì)CLH鎖進(jìn)行了java實(shí)現(xiàn),實(shí)現(xiàn)中用到了ThreadLocal類型,于是我發(fā)現(xiàn)我好像對(duì)ThreadLocal也不太熟,于是去看openjdk的源碼,又發(fā)現(xiàn)ThreadLocal的內(nèi)部類ThreadLocalMap中的Entry是繼承自WeakReference,好了,既然這幾個(gè)我好像都沒(méi)弄得很明白過(guò),所以我決定先了解一下Reference。

在我們平時(shí)開(kāi)發(fā)過(guò)程中很少會(huì)遇到需要與各種不同類型的reference打交道的時(shí)候,所以很多時(shí)候我們?cè)谧约簩懙拇a中很少會(huì)碰到需要使用不同的reference類型,可能很多人也會(huì)向我這樣,想要深入學(xué)習(xí)一下jdk源碼或者其他某些框架的源碼的時(shí)候才會(huì)看到諸如WeakReference這樣的類型。

問(wèn)題

假設(shè)在一個(gè)應(yīng)用中,需要從一個(gè)名為test的數(shù)據(jù)庫(kù)表中獲取數(shù)據(jù)。但凡有點(diǎn)經(jīng)驗(yàn)的開(kāi)發(fā)人員都會(huì)避免應(yīng)用獲取相同的數(shù)據(jù)每次都去查詢數(shù)據(jù)庫(kù),因?yàn)镮/O操作過(guò)去頻繁勢(shì)必會(huì)降低應(yīng)用性能。

顯然,我們首先想到的就是使用緩存。應(yīng)用首先查詢緩存,如果需要的數(shù)據(jù)存在直接拿來(lái)用就好;如果緩存未命中,才去數(shù)據(jù)庫(kù)查詢,并且把查詢到的數(shù)據(jù)放入緩存,以便下次應(yīng)用發(fā)起相同請(qǐng)求時(shí)可以直接從緩存獲取數(shù)據(jù)而不用再次去數(shù)據(jù)庫(kù)查詢。

使用緩存會(huì)提高性能嗎?

答案是這需要根據(jù)具體情況分析,如果從test獲取需要緩存的數(shù)據(jù)量較少,使用緩存會(huì)非常合適且一定會(huì)提升性能。但假若需要從test表查詢放到緩存里的數(shù)據(jù)量非常大,那就會(huì)出現(xiàn)一個(gè)問(wèn)題:由于數(shù)據(jù)量過(guò)大可能會(huì)導(dǎo)致內(nèi)存不足,而不單單是提升性能了。假如說(shuō)把表中所有數(shù)據(jù)都放入緩存,那么緩存的可能會(huì)占據(jù)大部分jvm的內(nèi)存或者索性直接產(chǎn)生一個(gè)OOM錯(cuò)誤。

解決方案

最佳的方案是如果我們可以創(chuàng)造一種可以按需擴(kuò)展和收縮的動(dòng)態(tài)緩存,當(dāng)我們的數(shù)據(jù)量需要而內(nèi)存充裕的時(shí)候可以適當(dāng)增加,但內(nèi)存不足是可以按不同方案對(duì)其進(jìn)行回收。

目的

這里引出的一個(gè)問(wèn)題,就是為什么要在Java中使用不同類型的reference?我們的應(yīng)用在運(yùn)行過(guò)程中會(huì)產(chǎn)生很多對(duì)象,這些對(duì)象駐留在內(nèi)存中,它們大小不同,重要性不同,使用頻率不同,生命周期不同,比如有些對(duì)象只要應(yīng)用啟動(dòng)就一直存活直到應(yīng)用停止,而有些對(duì)象生命周期與創(chuàng)建它的線程相同,還有些對(duì)象只作臨時(shí)變量短時(shí)間就消亡,再比如某些緩存數(shù)據(jù),內(nèi)存充裕的時(shí)候可以存活,內(nèi)存不足的時(shí)候可能需要被首先犧牲被回收,所以很容易想象對(duì)于不同的對(duì)象,我們希望對(duì)他們的創(chuàng)建銷毀采取不同的策略,可是不幸的是java不像C一樣可以由開(kāi)發(fā)者決定對(duì)象的析構(gòu)銷毀,而是將管理內(nèi)存的活統(tǒng)一交給了jvm進(jìn)行g(shù)c,但jvm顯然不知道這些對(duì)象的區(qū)別。

于是設(shè)計(jì)者們?cè)趈ava 1.2加入了reference,使jvm可以對(duì)不同的reference對(duì)象采取不同的回收策略以達(dá)到提高應(yīng)用性能的目的。

java.lang.ref 包

實(shí)際上java.lang.ref包中就有以下幾種不同的reference類型,分別是:

StrongReference

SoftReference

WeakReference

PhantomReference

FinalReference

StrongReference

我們發(fā)現(xiàn)在類圖中我們并沒(méi)有發(fā)現(xiàn) StrongReference 類型,原因是我們平時(shí)寫的代碼基本上都是 StrongReference 。我們最常的創(chuàng)建對(duì)象方式就是 new 一個(gè)對(duì)象,然后將其賦值給一個(gè)聲明為這個(gè)對(duì)象的類型及其父類的引用。如果對(duì)象有一個(gè) StrongReference ,那么這個(gè)對(duì)象將不會(huì)被gc回收。

舉例

HelloWorld hello = new HelloWorld();

這里 hello 就是一個(gè) HelloWorld 對(duì)象的 StrongReference。

SoftReference

如果一個(gè)對(duì)象沒(méi)有 StrongReference 但存在一個(gè) SoftReference ,那么 gc 將會(huì)在虛擬機(jī)需要釋放一些內(nèi)存的時(shí)候回收這個(gè)對(duì)象??梢酝ㄟ^(guò)對(duì)對(duì)象的 SoftReference 調(diào)用 get() 方法獲取該對(duì)象。如果這個(gè)對(duì)象沒(méi)有被 gc 回收,則返回此對(duì)象,否則返回 null 。

WeakReference

如果一個(gè)對(duì)象沒(méi)有 StrongReference 但有存在一個(gè) WeakReference ,那么 gc 將會(huì)在下一次運(yùn)行時(shí)對(duì)其進(jìn)行回收,哪怕虛擬機(jī)的內(nèi)存還足夠多。

PhantomReference 與 FinalReference

如果某個(gè)對(duì)象沒(méi)有以上這些類型的引用,那么它可能有一個(gè) PhantomReference 。PhantomReference 不能用于直接訪問(wèn)對(duì)象。調(diào)用 get() 方法都會(huì)返回 null 。

FinalReference 與虛擬機(jī)密切相關(guān),這里先挖個(gè)坑,下次再具體解析。

對(duì)象可達(dá)性判斷

當(dāng)前主流java虛擬機(jī)都是采用 GC Roots Tracing 算法,比如 Sun 的 Hotspot 虛擬機(jī)便是采用該算法。java虛擬機(jī)進(jìn)行g(shù)c時(shí),判斷一個(gè)對(duì)象的被引用情況決定是否回收,都是從根節(jié)點(diǎn)引用(Root set of Reference)開(kāi)始標(biāo)識(shí)可達(dá)路徑的。對(duì)于某個(gè)對(duì)象可能會(huì)存在其多個(gè)引用,且這多個(gè)引用的類型不同。

如下圖所示:

Root Tracing 算法根據(jù)以下兩個(gè)原則標(biāo)記對(duì)象的可達(dá)性:

單一路徑中,以最弱的引用為準(zhǔn)

多路徑中,以最強(qiáng)的引用為準(zhǔn)

如上圖所示,對(duì)對(duì)象4存在3條引用路徑:(1)(4),(2)(5),(3)(6)。那么從根對(duì)象到對(duì)象4的最強(qiáng)引用時(shí)(2)(5),因?yàn)?2)和(5)都是強(qiáng)引用。如果對(duì)象4僅存在一條(1)(4)引用,那么對(duì)它的引用就是最弱的引用為準(zhǔn),也就是 SoftReference ,對(duì)象4就是 softly-reachable 對(duì)象。

不同類型 reference java 代碼舉例

package com.example.reference;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
public class ReferenceExample {
  private String status ="Hi I am active";
  public String getStatus() {
    return status;
  }
  public void setStatus(String status) {
    this.status = status;
  }
  @Override
  public String toString() {
    return "ReferenceExample [status=" + status + "]";
  }
  public void strongReference()
  {
    ReferenceExample ex = new ReferenceExample();
    System.out.println(ex);
  }
  public void softReference()
  {
    SoftReference<ReferenceExample> ex = new SoftReference<ReferenceExample>(getRefrence());
    System.out.println("Soft refrence :: " + ex.get());
  }
  public void weakReference()
  {
    int counter=0;
    WeakReference<ReferenceExample> ex = new WeakReference<ReferenceExample>(getRefrence());
    while(ex.get()!=null)
    {
      counter++;
      System.gc();
      System.out.println("Weak reference deleted after:: " + counter + ex.get());
    }
  }
  public void phantomReference() throws InterruptedException
  {
    final ReferenceQueue queue = new ReferenceQueue();
    PhantomReference<ReferenceExample> ex = new PhantomReference<ReferenceExample>(getRefrence(),queue);
    System.gc();
    queue.remove();
    System.out.println("Phantom reference deleted after");
  }
  private ReferenceExample getRefrence()
  {
    return new ReferenceExample();
  }
  public static void main(String[] args) {
    ReferenceExample ex = new ReferenceExample();
    ex.strongReference();
    ex.softReference();
    ex.weakReference();
    try {
      ex.phantomReference();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output :
ReferenceExample [status=Hi I am active]
Soft refrence :: ReferenceExample [status=Hi I am active]
Weak reference deleted after:: 1null
Phantom reference deleted after

總結(jié)

通過(guò)對(duì)以上各類型的 reference 介紹可以發(fā)現(xiàn)其實(shí) reference 主要是用來(lái)與虛擬機(jī) gc 進(jìn)行交互,使得虛擬機(jī)根據(jù)對(duì)象的不同引用類型,對(duì)其采用不同的內(nèi)存回收策略。

strong 引用的對(duì)象正常情況下不會(huì)被回收,soft 引用的對(duì)象會(huì)在出現(xiàn) OOM 錯(cuò)誤之前被回收,而 weak 引用的對(duì)象在下一次 gc 的時(shí)候就會(huì)被回收,對(duì) reference 的基本理解就差不多了。

至于 PhantomReference 與 FinalReference 下次再講。

以上這篇java中的Reference類型用法說(shuō)明就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 在SpringBoot項(xiàng)目中使用Spring Cloud Sentinel實(shí)現(xiàn)流量控制

    在SpringBoot項(xiàng)目中使用Spring Cloud Sentinel實(shí)現(xiàn)流量控制

    隨著微服務(wù)架構(gòu)的流行,服務(wù)之間的調(diào)用變得越來(lái)越頻繁和復(fù)雜,流量控制是保障系統(tǒng)穩(wěn)定性的重要手段之一,它可以幫助我們避免因過(guò)載而導(dǎo)致的服務(wù)不可用,本文將介紹如何在Spring Boot項(xiàng)目中使用Spring Cloud Sentinel來(lái)實(shí)現(xiàn)流量控制,需要的朋友可以參考下
    2024-08-08
  • JWT原理與java操作jwt驗(yàn)證詳解

    JWT原理與java操作jwt驗(yàn)證詳解

    這篇文章主要介紹了JWT原理與java操作jwt驗(yàn)證,詳細(xì)分析了JWT的基本概念、原理與java基于JWT進(jìn)行token驗(yàn)證的相關(guān)操作技巧,需要的朋友可以參考下
    2023-06-06
  • 詳解java枚舉用法及實(shí)例

    詳解java枚舉用法及實(shí)例

    這篇文章主要介紹了Java枚舉詳解及使用實(shí)例,本文直接給出實(shí)例代碼,需要的朋友可以參考下
    2017-04-04
  • SpringBoot+Mybatis項(xiàng)目使用Redis做Mybatis的二級(jí)緩存的方法

    SpringBoot+Mybatis項(xiàng)目使用Redis做Mybatis的二級(jí)緩存的方法

    本篇文章主要介紹了SpringBoot+Mybatis項(xiàng)目使用Redis做Mybatis的二級(jí)緩存的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • mybatis-plus復(fù)合主鍵的使用

    mybatis-plus復(fù)合主鍵的使用

    本文主要介紹了mybatis-plus復(fù)合主鍵的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 永中文檔在線轉(zhuǎn)換服務(wù)Swagger調(diào)用說(shuō)明

    永中文檔在線轉(zhuǎn)換服務(wù)Swagger調(diào)用說(shuō)明

    這篇文章主要為大家介紹了永中文檔在線轉(zhuǎn)換服務(wù)Swagger調(diào)用說(shuō)明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • springBoot快速訪問(wèn)工程目錄下的靜態(tài)資源

    springBoot快速訪問(wèn)工程目錄下的靜態(tài)資源

    springboot工程,是沒(méi)有webapp文件夾的,靜態(tài)文件放在src/main/resources/static文件夾下即可,模板文件放在src/main/resources/templates下,本文給大家介紹springBoot快速訪問(wèn)工程目錄下的靜態(tài)資源的相關(guān)知識(shí),一起看看吧
    2021-06-06
  • Java打印數(shù)組的三種方法整理

    Java打印數(shù)組的三種方法整理

    許多學(xué)編程專業(yè)的同學(xué)面試的時(shí)候,考官都會(huì)問(wèn)到Java如何打印數(shù)組這樣的問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Java打印數(shù)組的三種方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 關(guān)于jdk環(huán)境變量的配置方式解讀

    關(guān)于jdk環(huán)境變量的配置方式解讀

    這篇文章主要介紹了關(guān)于jdk環(huán)境變量的配置方式解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 確保SpringBoot定時(shí)任務(wù)只執(zhí)行一次的常見(jiàn)方法小結(jié)

    確保SpringBoot定時(shí)任務(wù)只執(zhí)行一次的常見(jiàn)方法小結(jié)

    在Spring Boot項(xiàng)目中,確保定時(shí)任務(wù)只執(zhí)行一次是一個(gè)常見(jiàn)的需求,這種需求可以通過(guò)多種方式來(lái)實(shí)現(xiàn),以下是一些常見(jiàn)的方法,它們各具特點(diǎn),可以根據(jù)項(xiàng)目的實(shí)際需求來(lái)選擇最合適的方法,需要的朋友可以參考下
    2024-10-10

最新評(píng)論