石建 | Fat Mind

          Reference思考

           一、Java數據類型

            數據類型就是對內存位置的抽象表達

          (很多編程語言都依賴于特定的計算機類型和對數據類型屬性的具體編譯實現,比如wordinteger數據類型的大小等;Java通過JVM保證數據所占存儲空間的大小不會隨硬件的改變發生變化)。

          1.   Primitive data type A primitive type is predefined by the language and is named by a reserved keyword. Primitive values do not share state with other primitive values. The eight primitive data types supported by the Java programming language

          原生類型是語言自身預先定義的,原生值不會與其他原生值共享狀態。有8中原生類型被Java語言支持,如下:

          byte8位)、short16位)、int32位)、long64位)、float(浮點數,32位)、double(浮點數,64位)、boolean1位,只有truefalse可取)、char16-bit Unicode character

          2.       復雜數據類型

          運行期動態創建,一切皆為對象。

          接口(定義行為)

          類(String objects are immutable, which means that once created, their values cannot be changed.

          數組

          引用(軟、弱、虛引用)



          二、Reference分類

          1. strong Reference :正常情況下的引用都屬于strong引用,如:String str = new String();strstrong reference。其它引用必須是顯式的聲明,如:SoftReference softRef = new SoftReferencne(str)softRef是弱引用。

          2. SoftReference :軟引用。在內存溢出前,垃圾收集器將回收其引用的對象;

          3. WeakReference :弱引用。任何垃圾回收,掃描到弱引用時,其引用的對象都會被回收。

          4. PhantomReference 不理解。

          補充:ReferenceQueue

          Reference queues, to which registered reference objects are appended by the garbage collector after the appropriate reachability changes are detected.

          當某個引用對象的可達性被垃圾搜集器改變或清除后,會被放入對應的 ReferenceQueue 中(如果注冊引用隊列)。

                 String str = new String("hello");

                 ReferenceQueue<String> refQuence = new ReferenceQueue<String>();

                 Str = null;

                 SoftReference<String> softRef =

                     new SoftReference<String>(str, refQuence);

          如上例:當“hello”對象被收回后,則softRef會被加入到ReferenceQueue

           

          三、 WeakHashMap簡單分析

          簡化WeakHashMap結構:

          class WeakHashMap<K, V> {

              private final ReferenceQueue<K> queue = new ReferenceQueue<K>();

              private Entry[] table;

              private static class Entry<K,V> extends WeakReference<K> implements Map.Entry<K,V> {

              }

          }

           

          分析:WeakHashMapput方法(Map對數據的保存也是通過數組實現)

          public V put(K key, V value) {

                  K k = (K) maskNull(key);

                  int h = HashMap.hash(k.hashCode());

                  Entry[] tab = getTable(); //獲取table(關鍵:調用expungeStaleEntries方法,清洗table數組中,value所指的實際對象已被GC

                  int i = indexFor(h, tab.length); //根據key.hash計算在數組的位置

                 //從此位置開始,遍歷單向鏈表,判斷此位置是否已經存在相同元素

                     //1.有。更新為value 

          //2.無,創建新的對象,置原頭部元素為自己的next,讓自身為單向鏈表頭部

                  for (Entry<K,V> e = tab[i]; e != null; e = e.next) {

                     //如果hash相等,且equals相等

                      if (h == e.hash && eq(k, e.get())) {

                          V oldValue = e.value;

                          if (value != oldValue)

                              e.value = value;

                          return oldValue;

                      }

                  }

                  modCount++;

                  Entry<K,V> e = tab[i];

                 //queueReferenceQueueh自身key計算得到的hash值,e指向單鏈表下一個節點next

                  tab[i] = new Entry<K,V>(k, value, queue, h, e);

                  if (++size >= threshold) //判斷數組容量是否需要擴充,策略:2

                      resize(tab.length * 2);

                  return null;

              }

           

          /*

          * 清洗已被gc對象的引用,釋放數組的容量

          */

          private void expungeStaleEntries() {

              Entry<K,V> e;

                  while ( (e = (Entry<K,V>) queue.poll()) != null) { //從隊列獲取第一個加入ReferenceQueue的引用,循環

                      int h = e.hash;

                      int i = indexFor(h, table.length);

                      Entry<K,V> prev = table[i];

                      Entry<K,V> p = prev;

                      while (p != null) { //檢查單鏈表的數據是否已陳舊,清洗

                          Entry<K,V> next = p.next;

                          if (p == e) { //若相等,說明引用的對象已被gc

                              if (prev == e)

                                  table[i] = next;

                              else

                                  prev.next = next;

                           //因為其引用對象被垃圾收集器改變可達性時,也會被放queue,所以強制設置其nextvaluenull,幫助gc收集其引用對象(不這樣的理解正確不?請大家指點)

                              e.next = null// Help GC

                              e.value = null; //  "   "

                              size--;

                              break;

                          }

                          prev = p;

                          p = next;

                      }

                  }

              }

           

          四、 總結

          引用也是屬于Java的比較特殊的數據類型,對于軟、弱引用的使用場景大多是“緩存”。

           

           

           

           

          posted on 2010-12-18 16:52 石建 | Fat Mind 閱讀(285) 評論(0)  編輯  收藏 所屬分類: 一點理解

          導航

          <2010年12月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          統計

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          搜索

          最新評論

          What 、How、Why,從細節中尋找不斷的成長點
          主站蜘蛛池模板: 洛浦县| 文水县| 濉溪县| 荔波县| 泰宁县| 澳门| 永定县| 精河县| 鄢陵县| 秭归县| 息烽县| 宜州市| 南漳县| 武隆县| 安化县| 张掖市| 林周县| 宜州市| 奉贤区| 保德县| 临沧市| 通河县| 涞水县| 始兴县| 崇文区| 宣汉县| 平顺县| 沙坪坝区| 蛟河市| 临武县| 大埔区| 海伦市| 蓬安县| 芒康县| 大同市| 沈阳市| 登封市| 新郑市| 全椒县| 利津县| 潍坊市|