<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:說說Netty對象池的實現(xiàn)原理?

          共 5926字,需瀏覽 12分鐘

           ·

          2024-06-04 09:00

          面試題大全:www.javacn.site

          Netty 作為一個高性能的網(wǎng)絡通訊框架,它內置了很多恰奪天工的設計,目的都是為了將網(wǎng)絡通訊的性能做到極致,其中「對象池技術」也是實現(xiàn)這一目標的重要技術。

          1.什么是對象池技術?

          對象池技術是一種重用對象以減少對象創(chuàng)建和銷毀帶來的開銷的方法。在對象池中,只有第一次訪問時會創(chuàng)建對象,并將其維護在內存中,當再次需要使用對象時,會直接從對象池中獲取對象,并在使用完畢后歸還給對象池,而不是頻繁地創(chuàng)建和銷毀對象。

          使用對象池技術的優(yōu)點有以下幾個:

          1. 提高性能:復用對象可以減少對象的創(chuàng)建和銷毀次數(shù),降低系統(tǒng)開銷,提高系統(tǒng)性能和吞吐量。
          2. 減少內存碎片:對象池可以避免頻繁地創(chuàng)建和銷毀對象,減少內存碎片的產生,提高內存利用率。
          3. 避免頻繁GC:減少了對象的創(chuàng)建和銷毀,可以減少垃圾回收(GC)的頻率,降低系統(tǒng)的負擔,提高系統(tǒng)的穩(wěn)定性。

          2.對象池基本使用

          Netty 對象池技術的核心實現(xiàn)類為 Recycler,Recycler 主要提供了以下 3 個方法:

          1. get():獲取一個可重復使用的對象,如果對象池中有空閑對象,則返回其中一個;否則會創(chuàng)建一個新對象。
          2. recycle(T, Handle):回收一個對象,將對象放回對象池中以便下次復用。
          3. newObject(Handle):當對象池中沒有可用對象時,此方法會被調用以創(chuàng)建新的對象實例。

          接下來我們寫一個 Recycler 對象池的使用 Demo,假設我們有一個 User 類,需要實現(xiàn) User 對象的復用,具體實現(xiàn)代碼如下:

          public class UserRecyclerDemo {
              private static final Recycler<User> userRecycler = new Recycler<User>() {
                  @Override
                  protected User newObject(Handle<User> handle) {
                      return new User(handle);
                  }
              };

              static final class User {
                  private String name;
                  private Recycler.Handle<User> handle;
                  public void setName(String name) {
                      this.name = name;
                  }
                  public String getName() {
                      return name;
                  }
                  public User(Recycler.Handle<User> handle) {
                      this.handle = handle;
                  }
                  public void recycle() {
                      handle.recycle(this);
                  }
              }

              public static void main(String[] args) {
                  User user1 = userRecycler.get();  // 1.從對象池獲取 User 對象
                  user1.setName("zhangsan");    // 2.設置 User 對象的屬性
                  user1.recycle();      // 3.回收對象到對象池
                  User user2 = userRecycler.get();  // 4.從對象池獲取對象
                  System.out.println(user1 == user2);
                  System.out.println(user2.getName());
              }
          }

          以上程序的執(zhí)行結果如下:

          true

          zhangsan

          從上述結果可以看出,當?shù)谝淮握{用 userRecycler.get() 時,因為對象池中尚未存在 user 對象,所以創(chuàng)建了 name 為“zhangsan”的對象。但第二次再調用 userRecycler.get() 時,因為對象池中已經(jīng)存在了 user 對象,所以直接從對象池中取出了 user 對象,所以 user1==user2 時,得到的結果是 true。

          3.對象池技術應用

          在 Netty 中,使用 Recycler 對象池管理對象的常見類有以下幾個:

          1. PooledHeapByteBuf:管理堆內存中的 ByteBuf 對象。
          2. PooledDirectByteBuf:管理堆外內存中的 ByteBuf 對象。
          3. ChannelOutboundBuffer.Entry:Netty 出站緩沖區(qū)(ChannelOutboundBuffer)中,每一個待發(fā)送的消息都包裝在一個 Entry 對象中。

          4.實現(xiàn)原理

          要搞清楚 Netty 對象池技術的實現(xiàn)原理,就要搞清楚 Netty 對象池的核心組件,以及組件之間的關系。

          Netty 對象池技術的實現(xiàn)依靠以下 4 大組件:

          1. Stack(棧):每個線程都關聯(lián)一個 Stack(使用 FastThreadLocal 進行存儲),用于存儲和管理該線程回收的對象。Stack 中存儲的是 DefaultHandle 對象,這些 DefaultHandle 對象包裝了實際要重用的對象。Stack 是與線程綁定的,每個線程從自己的 Stack 中獲取對象。
          2. WeakOrderQueue(弱序隊列):當某個線程(非主線程)回收對象時,這些對象不會直接放入主線程的 Stack 中,而是放入 WeakOrderQueue 中。WeakOrderQueue 存儲的是從其他線程回收的對象,這些對象被包裝在 DefaultHandle 中。WeakOrderQueue 與 Stack 關聯(lián),但屬于非主線程。當主線程的 Stack 為空時,會嘗試從 WeakOrderQueue 中獲取對象。
          3. Link(鏈表):WeakOrderQueue 中的存儲單元,用于存儲回收的對象。Link 中存儲的是 DefaultHandle 對象數(shù)組,這些數(shù)組包含從其他線程回收的對象。
          4. DefaultHandle:對象的包裝類,在 Recycler 中緩存的對象都會包裝成 DefaultHandle 類。DefaultHandle 中存儲了實際要重用的對象,以及與之相關的元數(shù)據(jù)。

          簡單來說,這 4 個組件的關系是,(每個)線程為了保證線程安全和高效性操作,所以會把使用的對象放到 Stack 棧中,且每個線程都有自己的 Stack 棧。當線程中的對象不再被使用時(也就是被回收時),并不會將回收對象直接放到 Stack 中(因為當前線程已經(jīng)不再使用了),此時會將對象存放到 WeakOrderQueue 隊列中,因為 WeakOrderQueue 隊列相當于“線程共享的區(qū)域”,這樣其他線程就可以方便的從 WeakOrderQueue 中獲取對象進行重用了。而 WeakOrderQueue 中的存儲單元是 Link 鏈表,它存儲的是對象池中的包裝對象 DefaultHandle,這就是這四大核心組件之間的關系。

          5.線程如何獲取對象?

          在 Netty 中,獲取對象池中對象的流程如下:

          1. 判斷 Stack:線程首先會嘗試從自己的 Stack 中獲取對象。如果 Stack 中有對象,則直接彈出(pop)并返回。
          2. Stack 為空:如果 Stack 為空,線程會檢查 WeakOrderQueue。如果 WeakOrderQueue 中有對象,則按照一定的規(guī)則(如“1/7規(guī)則”,每 7 個移動 1 個)將部分對象轉移到 Stack 中,然后從 Stack 中彈出并返回。
          3. 創(chuàng)建新對象:如果 Stack 和 WeakOrderQueue 都為空,線程會調用 newObject() 方法創(chuàng)建一個新的對象,并包裝成 DefaultHandle 后放入 Stack 中,然后返回該對象。

          通過這樣的設計,Netty 的 Recycler 對象池技術能夠高效地重用對象,減少內存分配和垃圾收集的開銷,提升性能。

          課后思考

          Netty 是如何利用池化技術管理內存的?講講它的具體實現(xiàn)?

          特殊說明

          以上內容來自我的《Java 面試突擊訓練營》,這門課程是有著 14 年工作經(jīng)驗(前 360 開發(fā)工程師),9 年面試官經(jīng)驗的我,花費 4 年時間打磨完成的一門視頻面試課。

          整個課程從 Java 基礎到微服務 Spring Cloud、從實際開發(fā)問題到場景題應有盡有,包含模塊如下:訓練營系統(tǒng)的帶領大家把 Java 常見的面試題過一遍,遇到一個問題,把這個問題相關的內容都給大家講明白,并且視頻支持永久觀看和一直更新。并且面試訓練營還提供 9 大就業(yè)服務。

          上完訓練營的課程之后,基本可以應對目前市面上絕大部分公司的面試了,幫你快速找到高薪工作,加我微信咨詢:GG_Stone【備注:訓練營】


          瀏覽 77
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天视频黄 | 国产美女极度色诱视频WWW | 水蜜桃在线视频 | 午夜成人精品视频免费在线观看 | 男人的天堂伊人 |