日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

重要方法的源码分析

發布時間:2024/4/13 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 重要方法的源码分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ThreadLocal主要方法源碼解析?

?

  • public T get() :get方法是先取出當前線程的ThreadLocalMap,然后調用map.getEntry方法,把本ThreadLocal的引用作為參數傳入,取出map中屬于本ThreadLocal的value
  • 注意這個map以及map中的key和value都是保存在線程中的,而不是保存在ThreadLocal中
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 getMap(Thread t) {return t.threadLocals; }

public void set(T value) :和setInitialValue()方法很類似

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

initialValue()

protected T initialValue() {return null; }

??該方法返回當前線程局部變量的初始化值。當第一次使用get方法訪問變量時調用該方法,但若該線程在這之前調用了set方法,則不會調用initialValue方法。正常情況下,該方法最多被調用一次,但是如果后續調 用了remove,然后再調用get,則該方法可能再次被調用。

withInitial()

public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {return new SuppliedThreadLocal<>(supplier); }

??用于創建一個線程局部變量,變量的初始化值通過調用Supplier的get方法來確定,例子如下:
import java.util.function.Supplier;

public class ThreadLocalDemo { public static void main(String args[]) {ThreadLocal<Integer> tl = ThreadLocal.withInitial(new Supplier<Integer>() {@Overridepublic Integer get() {// TODO Auto-generated method stubreturn new Integer(8);}});System.out.println(tl.get());} }

輸出為:8

public void remove()方法

public void remove() {ThreadLocalMap m = getMap(Thread.currentThread());if (m != null)m.remove(this); }private void remove(ThreadLocal<?> key) {Entry[] tab = table;int len = tab.length;int i = key.threadLocalHashCode & (len-1);for (Entry e = tab[i];e != null;e = tab[i = nextIndex(i, len)]) {if (e.get() == key) {e.clear();expungeStaleEntry(i);return;}} }

?

?該方法用于清除當前線程局部變量的值。變量值被清除后,若當前線程隨后通過get讀取該變量的值,則initialValue方法會再次被調用對變量進行初始化,除非在此期間調用了set方法。

??經過上面的分析,可知通過ThreadLocal創建的變量是維護在線程內部的,這就意味著線程只要不退出,那么對象的引用將一直存在。當線程退出的時候會進行一些清理工作,如下所示:

private void exit() {if (group != null) {group.threadTerminated(this);group = null;}/* Aggressively null out all reference fields: see bug 4006245 */target = null;//加速資源清理,threadLocals為ThreadLocal.ThreadLocalMap類型threadLocals = null;inheritableThreadLocals = null;inheritedAccessControlContext = null;blocker = null;uncaughtExceptionHandler = null; }

此方法為private型,通過系統調用,給線程一個機會在其實際退出之前清理資源。

??上面多次出現了ThreadLocalMap類,有必要說明一下。ThreadLocalMap的實現采用了弱引用,弱引用在垃圾回收的時候被發現就會被回收。ThreadLocalMap內部由一系列的Entry構成,每一個Entry都是WeakReference<ThreadLocal>類型的:

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

內部維護一個Entry數組,用于存放線程的變量

private Entry[] table;

例子:

public class ThreadLocalDemo implements Runnable{ private static ThreadLocal<Integer> tl=new ThreadLocal<Integer>(); @Override public void run() {// TODO Auto-generated method stubif(tl.get()==null)tl.set(new Integer(1));System.out.print(tl.get()+"\t");}public static void main(String args[]) {int k=0;for(int i=0;i<1000;i++) {Thread t=new Thread(new ThreadLocalDemo());t.start();}} }

輸出全為1,即每一個線程都維護自己的一個變量副本

?

總結

以上是生活随笔為你收集整理的重要方法的源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。