1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問(wèn)題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
      Android中的Message類以及Java對(duì)象池的實(shí)現(xiàn)-創(chuàng)新互聯(lián)

      在Android的android.os.Message類的文檔中有這么一句話:

      創(chuàng)新互聯(lián)建站是一家專注于成都網(wǎng)站制作、成都做網(wǎng)站與策劃設(shè)計(jì),鄲城網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:鄲城等地區(qū)。鄲城做網(wǎng)站價(jià)格咨詢:13518219792
      While the constructor of Message is public, the best way to get one of these is to call Message.obtain() or one of the Handler.obtainMessage() methods, which will pull them from a pool of recycled objects.

      大意是說(shuō),雖然Message類的構(gòu)造方法是public的,你可以直接通過(guò)new來(lái)創(chuàng)建一個(gè)新的對(duì)象,但是最好還是通過(guò)Message.obtain()或者Handler.obtainMessage()來(lái)創(chuàng)建一個(gè)新的Message對(duì)象,因?yàn)檫@兩個(gè)方法會(huì)重用之前創(chuàng)建的但是已經(jīng)不再使用了的對(duì)象實(shí)例。

      這句話不禁引起了我的興趣,因?yàn)橹拔覍戇^(guò)一篇博客《Pool, SimplePool與SynchronizedPool》,在這篇博客里面仔細(xì)分析了Android是如何實(shí)現(xiàn)一個(gè)對(duì)象池的。里面提到VelocityTracker就是用SynchronizedPool來(lái)實(shí)現(xiàn)對(duì)象重用的,代碼如下:

      VelocityTracker tracker = VelocityTracker.obtain(); 
      tracker.recycle();

      Message類看起來(lái)也略有相似,不過(guò)經(jīng)過(guò)閱讀Message類的源代碼,發(fā)現(xiàn)我錯(cuò)了,Message類使用了另一種巧妙的方法來(lái)實(shí)現(xiàn)對(duì)象重用。

      好了,不賣關(guān)子了,Message類使用了一個(gè)鏈表來(lái)實(shí)現(xiàn)對(duì)象池,而且是一個(gè)前端鏈表,即在前端插入和刪除的鏈表,避免了插入和刪除的時(shí)候遍歷整個(gè)鏈表。是不是有點(diǎn)出人意料?

      首先看一下這段代碼,去除了Message中其他的攜帶消息信息的字段。已經(jīng)很明顯可以看出來(lái)是一個(gè)鏈表了吧。

      public final class Message implements Parcelable {
          // 省略其他代碼
              
          Message next;                                          // (1)
      
          private static final Object sPoolSync = new Object();  // (2)
          private static Message sPool;                          // (3)
          private static int sPoolSize = 0;                      // (4)
      
          private static final int MAX_POOL_SIZE = 50;
          
          // 省略其他代碼
      }

      (1) 聲明了next指針

      (2) 對(duì)象鎖,Message對(duì)象池是線程安全的,這樣就需要在向?qū)ο蟪厣暾?qǐng)和歸還對(duì)象時(shí)使用鎖

      (3) 這里是關(guān)鍵,一個(gè)靜態(tài)的Message對(duì)象,這就是這個(gè)鏈表的頭指針了,因?yàn)槭穷愖兞浚虼耍麄€(gè)JVM中只有一個(gè)

      (4) 當(dāng)前對(duì)象池的大小,后面還限制了這個(gè)Message對(duì)象池中的對(duì)象個(gè)數(shù)大為50

      用圖形表示如下:

      Android中的Message類以及Java對(duì)象池的實(shí)現(xiàn)

      繼續(xù)閱讀代碼,又發(fā)現(xiàn)了一個(gè)讓人困惑的問(wèn)題,看這個(gè)方法:

          public static Message obtain() {
              synchronized (sPoolSync) {      // (1)
                  if (sPool != null) {
                      Message m = sPool;      // (2)
                      sPool = m.next;         // (3)
                      m.next = null;          // (4)
                      sPoolSize--;            // (5)
                      return m;
                  }
              }
              return new Message();
          }

      這也很容易理解:

      (1) 獲取鎖,這里毫無(wú)疑義

      (2) 當(dāng)頭指針指向的對(duì)象不為null時(shí),將這個(gè)對(duì)象賦值給m

      (3) 將頭指針指向m的next指針

      (4) 將m的next指向null,到這里位置,我們從以sPool為頭指針的鏈表中取出了第一個(gè)元素

      (5) 將鏈表size減1

      看起來(lái)沒(méi)錯(cuò),疑問(wèn)是,當(dāng)?shù)谝淮潍@取對(duì)象的時(shí)候sPool肯定為null,那么這個(gè)if語(yǔ)句肯定不會(huì)執(zhí)行,會(huì)直接執(zhí)行最后一句return new Message(),直接創(chuàng)建一個(gè)對(duì)象?這樣不是毫無(wú)意義了么?

      看到這里,似乎感覺(jué)發(fā)現(xiàn)了一個(gè)Android的bug,會(huì)有這么明顯的bug么?當(dāng)然不會(huì),靜下心來(lái)繼續(xù)讀代碼,讀到這里的時(shí)候豁然開朗了:

          public void recycle() {
              clearForRecycle();                        // (1)
      
              synchronized (sPoolSync) {
                  if (sPoolSize < MAX_POOL_SIZE) {      // (2)
                      next = sPool;                     // (3)
                      sPool = this;                     // (4)
                      sPoolSize++;
                  }
              }
          }

      (1) 重置Message中攜帶的消息

      (2) 檢查當(dāng)前對(duì)象池的大小是不是已經(jīng)超過(guò)了大值,如果當(dāng)前隊(duì)列已經(jīng)滿了,就不管這個(gè)對(duì)象了,讓JVM的GC回收好了,這里保證了性能的同時(shí)兼顧了內(nèi)存消耗

      (3) 將當(dāng)前對(duì)象next指針指向頭指針sPool指向的對(duì)象

      (4) 將頭指針sPool指向當(dāng)前對(duì)象,然后將對(duì)象池大小加1

      到這里就明白了:這篇博客開頭的那句話其實(shí)背后還有一些潛臺(tái)詞,那就是你必須顯式的調(diào)用一下recycle()將當(dāng)前的Message對(duì)象歸還到對(duì)象池,這個(gè)對(duì)象池才能發(fā)揮其效果,不調(diào)用recycle()方法,對(duì)象不會(huì)歸還,會(huì)被JVM GC回收。

      也就是說(shuō)下面兩句話必須是成對(duì)出現(xiàn)的,不用obtain()而調(diào)用recycle()會(huì)導(dǎo)致不停的創(chuàng)建Message對(duì)象直到超過(guò)MAX_POOL_SIZE的限制而被對(duì)象池扔掉;通過(guò)obtain()申請(qǐng)對(duì)象而不用recycle()歸還會(huì)導(dǎo)致對(duì)象池被消耗干凈而不停申請(qǐng)新對(duì)象。

      Message msg = Message.obtain(); 
      msg.recycle();

      所以文檔再完整還是不如看代碼。

      對(duì)于通過(guò)SynchronizedPool來(lái)實(shí)現(xiàn)對(duì)象池和這種通過(guò)鏈表來(lái)實(shí)現(xiàn)對(duì)象池兩種方法,我看不出來(lái)各自有何優(yōu)缺點(diǎn),這兩種方法很相似,實(shí)現(xiàn)的功能也相似,唯一的不同在于,前者似乎更容易擴(kuò)展。也許你自己在其他項(xiàng)目中需要對(duì)象池的時(shí)候,可以借鑒一下這兩種方法。

      另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。


      分享題目:Android中的Message類以及Java對(duì)象池的實(shí)現(xiàn)-創(chuàng)新互聯(lián)
      本文來(lái)源:http://ef60e0e.cn/article/dhjcgj.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        拉孜县| 汉沽区| 龙岩市| 新建县| 乃东县| 门源| 桑日县| 临桂县| 秀山| 无锡市| 石嘴山市| 泗水县| 柳河县| 清镇市| 资溪县| 襄樊市| 盐亭县| 怀来县| 富顺县| 古田县| 梅州市| 威宁| 乡宁县| 鄯善县| 安龙县| 鲁山县| 红原县| 文山县| 舞钢市| 涡阳县| 原平市| 牙克石市| 积石山| 苏尼特左旗| 凉山| 饶平县| 南京市| 涿鹿县| 五大连池市| 赤峰市| 襄樊市|