最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中的引用類型和使用場(chǎng)景詳細(xì)

 更新時(shí)間:2021年10月08日 14:18:28   作者:Grey  
這篇文章介紹的是Java中的引用類型和使用場(chǎng)景,主要內(nèi)容展開Java中的引用類型,有強(qiáng)引用、軟引用 、弱引用、虛引用,需要的朋友可以參考一下

Java中的引用類型有哪幾種?

Java中的引用類型分成 強(qiáng)引用 , 軟引用 , 弱引用 , 虛引用 。

1、強(qiáng)引用

沒有引用指向這個(gè)對(duì)象,垃圾回收會(huì)回收

package git.snippets.juc;

import java.io.IOException;

public class NormalRef {
    public static void main(String[] args) throws IOException {
        M m = new M();
        m = null;
        System.gc();
        System.in.read();
    }
    static class M {
        M() {}
        @Override
        protected void finalize() throws Throwable {
            System.out.println("finalized");
        }
    }
}

2、軟引用

當(dāng)有一個(gè)對(duì)象被一個(gè)軟引用所指向的時(shí)候,只有系統(tǒng)內(nèi)存不夠用的時(shí)候,才會(huì)被回收,可以用做緩存(比如緩存大圖片)

示例如下代碼:注:執(zhí)行以下方法的時(shí)候,需要把VM options設(shè)置為 -Xms20M -Xmx20M 。

package git.snippets.juc;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.concurrent.TimeUnit;

/**
 * heap將裝不下,這時(shí)候系統(tǒng)會(huì)垃圾回收,先回收一次,如果不夠,會(huì)把軟引用干掉
 * 軟引用,適合做緩存
 * 示例需要把Vm options設(shè)置為:-Xms20M -Xmx20M
 */
public class SoftRef {
    public static void main(String[] args) throws IOException {
        SoftReference<byte[]> reference = new SoftReference<>(new byte[1024 * 1024 * 10]);
        System.out.println(reference.get());
        System.gc();
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(reference.get());
        byte[] bytes = new byte[1024 * 1024 * 10];
        System.out.println(reference.get());
        System.in.read();
    }
}

上述代碼在第一次執(zhí)行 System.out.println(reference.get()) 時(shí)候,由于堆的最大最小值都是 20M ,而我們分配的 byte 數(shù)組是 10M ,沒有超過最大堆內(nèi)存,所以執(zhí)行垃圾回收,軟引用不被回收,后續(xù)又調(diào)用了 byte[] bytes = new byte[1024 * 1024 * 10]; 再次分配了 10M 內(nèi)存,此時(shí)堆內(nèi)存已經(jīng)超過設(shè)置的最大值,會(huì)進(jìn)行回收,所以最后一步的 System.out.println(reference.get()); 無法 get 到數(shù)據(jù)。

3、弱引用

只要垃圾回收,就會(huì)回收。如果有一個(gè)強(qiáng)引用指向弱引用中的這個(gè)對(duì)象,如果這個(gè)強(qiáng)引用消失,這個(gè)對(duì)象就應(yīng)該被回收。一般用在容器里面。

代碼示例如下:

package git.snippets.juc;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * 弱引用遭到gc就會(huì)回收
 * ThreadLocal應(yīng)用,緩存應(yīng)用,WeakHashMap
 */
public class WeakRef {
    public static void main(String[] args) {
        WeakReference<T> reference = new WeakReference<>(new T());
        System.out.println(reference.get());
        System.gc();
        System.out.println(reference.get());
    }
    static class T {
        T() {}
        @Override
        protected void finalize() {
            System.out.println("finalized");
        }
    }
}

如果執(zhí)行了一次 GC , reference.get() 獲取到的值即為空。

4、弱引用的使用場(chǎng)景

弱引用的一個(gè)典型應(yīng)用場(chǎng)景就是 ThreadLocal ,以下是 ThreadLocal 的的簡(jiǎn)要介紹

set方法:

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }


get方法:

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }


ThreadLocalMap 是當(dāng)前線程的一個(gè)成員變量,所以,其他線程無法讀取當(dāng)前線程設(shè)置的 ThreadLocal 值。

ThreadLocal.ThreadLocalMap threadLocals = null;


ThreadLocal 的主要應(yīng)用場(chǎng)景

場(chǎng)景一:每個(gè)線程需要一個(gè)獨(dú)享的對(duì)象:假設(shè)有100個(gè)線程都需要用到 SimpleDateFormat 類來處理日期格式,如果共用一個(gè) SimpleDateFormat ,就會(huì)出現(xiàn)線程安全問題,導(dǎo)致數(shù)據(jù)出錯(cuò),如果加鎖,就會(huì)降低性能,此時(shí)使用 ThreadLocal ,給每個(gè)線程保存一份自己的本地 SimpleDateFormat ,就可以同時(shí)保證線程安全和性能需求。

場(chǎng)景二:每個(gè)線程內(nèi)部保存全局變量,避免傳參麻煩:假設(shè)一個(gè)線程的作用是拿到前端用戶信息,逐層執(zhí)行 Service1 , Service2 , Service3 , Service4 層的業(yè)務(wù)邏輯,其中每個(gè)業(yè)務(wù)層都會(huì)用到用戶信息,此時(shí)一個(gè)解決辦法就是將 User 信息對(duì)象作為參數(shù)層層傳遞,但是這樣會(huì)導(dǎo)致代碼冗余且不利于維護(hù)。此時(shí)可以將 User 信息對(duì)象放入當(dāng)前線程的 Threadlocal 中,就變成了全局變量,在每一層業(yè)務(wù)層中,需要使用的時(shí)候直接從 Threadlocal 中獲取即可。

場(chǎng)景三: Spring 的聲明式事務(wù),數(shù)據(jù)庫(kù)連接寫在配置文件,多個(gè)方法可以支持一個(gè)完整的事務(wù),保證多個(gè)方法是用的同一個(gè)數(shù)據(jù)庫(kù)連接(其實(shí)就是放在 ThreadLocal 里面)

了解了 ThreadLocal 簡(jiǎn)要介紹以后,我們可以深入理解一下 ThreadLocal 的一個(gè)內(nèi)部原理,前面提到, ThreadLocal 的 set 方法實(shí)際上是往當(dāng)前線程的一個(gè) threadLocals 表中插入一條記錄,而這個(gè)表中的記錄都存在一個(gè) Entry 對(duì)象中,這個(gè)對(duì)象有一個(gè)key和一個(gè)value, key 就是當(dāng)前線程的 ThreadLocal 對(duì)象。

static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }

這個(gè) Entry 對(duì)象繼承了 WeakReference , 且構(gòu)造函數(shù)調(diào)用了 super(k) , 所以 Entry 中的 key 是通過一個(gè)弱引用指向的 ThreadLocal ,所以,我們?cè)谥鞣椒ㄖ姓{(diào)用

ThreadLocal<Object> tl = new ThreadLocal<>();


tl 是通過強(qiáng)引用指向這個(gè) ThreadLocal 對(duì)象。

當(dāng)前線程的 threadLocalMap 中的 key 是通過弱引用指向 ThreadLocal 對(duì)象,這樣就可以保證,在 tl 指向空以后,這個(gè) ThreadLocal 會(huì)被回收,否則,如果 threadLocalMap 中的 key 是強(qiáng)引用指向 ThreadLocal 對(duì)象話,這個(gè) ThreadLocal 對(duì)象永遠(yuǎn)不會(huì)被回收。就會(huì)導(dǎo)致內(nèi)存泄漏。

但是,即便 key 用弱引用指向 ThreadLocal 對(duì)象, key 值被回收后, Entry 中的 value 值就無法被訪問到了,且 value 是通過強(qiáng)引用關(guān)聯(lián),所以,也會(huì)導(dǎo)致內(nèi)存泄漏,所以,每次在 ThreadLocal 中的對(duì)象不用了,記得要調(diào)用 remove 方法,把對(duì)應(yīng)的 value 也給清掉。

5、虛引用

用于管理堆外內(nèi)存回收

虛引用關(guān)聯(lián)了一個(gè)對(duì)象,以及一個(gè)隊(duì)列,只要垃圾回收,虛引用就被回收,一旦虛引用被回收,虛引用會(huì)被裝到這個(gè)隊(duì)列,并會(huì)收到一個(gè)通知(如果有值入隊(duì)列,會(huì)得到一個(gè)通知)所以,如果想知道虛引用何時(shí)被回收,就只需要不斷監(jiān)控這個(gè)隊(duì)列是否有元素加入進(jìn)來了。

虛引用里面關(guān)聯(lián)的對(duì)象用get方法是無法獲取的。

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.LinkedList;
import java.util.List;

// 配置 -Xms20M -Xmx20M
public class PhantomRef {
    private static final List<Object> LIST = new LinkedList<>();
    private static final ReferenceQueue<P> QUEUE = new ReferenceQueue<>();


    public static void main(String[] args) {
        PhantomReference<P> phantomReference = new PhantomReference<>(new P(), QUEUE);
        new Thread(() -> {
            while (true) {
                LIST.add(new byte[1024 * 1024]);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
                System.out.println(phantomReference.get());
            }
        }).start();

        new Thread(() -> {
            while (true) {
                Reference<? extends P> poll = QUEUE.poll();
                if (poll != null) {
                    System.out.println("--- 虛引用對(duì)象被jvm回收了 ---- " + poll);
                }
            }
        }).start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    static class P {
        @Override
        protected void finalize() throws Throwable {
            System.out.println("finalized");
        }
    }
}

6、虛引用的應(yīng)用場(chǎng)景

JDK的 NIO 包中有一個(gè) DirectByteBuffer , 這個(gè) buffer 指向的是堆外內(nèi)存,所以當(dāng)這個(gè) buffer 設(shè)置為空的時(shí)候,Java的垃圾回收無法回收,所以,可以用虛引用來管理這個(gè) buffer ,當(dāng)我們檢測(cè)到這個(gè)虛引用被垃圾回收器回收的時(shí)候,可以做出相應(yīng)的處理,去回收堆外內(nèi)存。

到此這篇關(guān)于Java中的引用類型和使用場(chǎng)景詳細(xì)的文章就介紹到這了,更多相關(guān)Java中的引用類型和使用場(chǎng)景內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringMVC和Spring的配置文件掃描包詳解

    SpringMVC和Spring的配置文件掃描包詳解

    這篇文章主要介紹了SpringMVC和Spring的配置文件掃描包,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2019-05-05
  • Java文件字符輸入流FileReader讀取txt文件亂碼的解決

    Java文件字符輸入流FileReader讀取txt文件亂碼的解決

    這篇文章主要介紹了Java文件字符輸入流FileReader讀取txt文件亂碼的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • SpringBoot應(yīng)用程序啟動(dòng)監(jiān)聽功能的常見方法

    SpringBoot應(yīng)用程序啟動(dòng)監(jiān)聽功能的常見方法

    應(yīng)用啟動(dòng)監(jiān)聽在?Spring?Boot?和其他框架中扮演著重要的角色,它們的主要作用是在應(yīng)用啟動(dòng)或關(guān)閉時(shí)觸發(fā)特定的操作或任務(wù),本文給大家介紹了SpringBoot應(yīng)用程序啟動(dòng)監(jiān)聽功能的常見方法,需要的朋友可以參考下
    2024-05-05
  • RedisKey的失效監(jiān)聽器KeyExpirationEventMessageListener問題

    RedisKey的失效監(jiān)聽器KeyExpirationEventMessageListener問題

    這篇文章主要介紹了RedisKey的失效監(jiān)聽器KeyExpirationEventMessageListener問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • java?stream使用指南之sorted使用及進(jìn)階方式

    java?stream使用指南之sorted使用及進(jìn)階方式

    這篇文章主要介紹了java?stream使用指南之sorted使用及進(jìn)階方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 你真的理解Java中的ArrayList嗎

    你真的理解Java中的ArrayList嗎

    這篇文章主要給大家介紹了關(guān)于Java中ArrayList的相關(guān)資料,ArrayList就是傳說中的動(dòng)態(tài)數(shù)組,用MSDN中的說法,就是Array的復(fù)雜版本,需要的朋友可以參考下
    2021-08-08
  • SpringBoot常用注解詳細(xì)整理

    SpringBoot常用注解詳細(xì)整理

    大家好,本篇文章主要講的是SpringBoot常用注解詳細(xì)整理,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • Spring BeanDefinition使用介紹

    Spring BeanDefinition使用介紹

    BeanDefinition是Spring框架中非常核心的概念,BeanDefinition是定義Bean的配置元信息接口,Spring根據(jù)BeanDefinition來定義Bean對(duì)象,簡(jiǎn)單說就是對(duì)Bean信息的定義
    2023-01-01
  • java web中使用cookie記住用戶的賬號(hào)和密碼

    java web中使用cookie記住用戶的賬號(hào)和密碼

    這篇文章主要介紹了java web中使用cookie記住用戶的賬號(hào)和密碼的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • Java+TestNG接口自動(dòng)化入門詳解

    Java+TestNG接口自動(dòng)化入門詳解

    本文主要介紹了Java+TestNG接口自動(dòng)化入門,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12

最新評(píng)論

溧水县| 分宜县| 邳州市| 北京市| 吉林省| 历史| 濉溪县| 甘洛县| 江城| 额济纳旗| 盐津县| 宁乡县| 红安县| 大足县| 甘洛县| 贞丰县| 来安县| 和静县| 陇西县| 洛南县| 海阳市| 乐陵市| 宁德市| 都昌县| 利辛县| 迁安市| 阿合奇县| 通化县| 阳曲县| 鹿邑县| 德惠市| 渝北区| 天镇县| 沙洋县| 白城市| 东源县| 夹江县| 崇文区| 兴城市| 三都| 陆丰市|