<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 25 整體設計:隊列設計思想、工作中使用場景 ## 引導語 本章我們學習了 LinkedBlockingQueue、ArrayBlockingQueue、SynchronousQueue、DelayQueue 四種隊列,四種隊列底層數據結構各不相同,使用場景也不相同,本章我們從設計思想和使用場景兩個大的方向做一些對比和總結。 ### 1 設計思想 首先我們畫出隊列的總體設計圖: ![](https://img.kancloud.cn/47/de/47dea6bff57ef395ed737ea795a2c2bc_1255x971.jpg) 從圖中我們可以看出幾點: 1. 隊列解耦了生產者和消費者,提供了生產者和消費者間關系的多種形式,比如 LinkedBlockingQueue、ArrayBlockingQueue 兩種隊列就把解耦了生產者和消費者,比如 SynchronousQueue 這種就把生產者和消費者相互對應(生產者的消息被消費者開始消費之后,生產者才能返回,為了方便理解,使用相互對應這個詞); 2. 不同的隊列有著不同的數據結構,有鏈表(LinkedBlockingQueue)、數組(ArrayBlockingQueue)、堆棧(SynchronousQueue)等; 3. 不同的數據結構,決定了入隊和出隊的姿勢是不同的。 接下來我們分別按照這幾個方面來總結分析一下。 #### 1.1 隊列的數據結構 鏈表結構的隊列就是 LinkedBlockingQueue,其特征如下: 1. 初始大小默認是 Integer 的最大值,也可以設置初始大小; 2. 鏈表元素通過 next 屬性關聯下一個元素; 3. 新增是從鏈表的尾部新增,拿是從鏈表頭開始拿。 數組結構的隊列是 ArrayBlockingQueue,特征如下: 1. 容量大小是固定的,不能動態擴容; 2. 有 takeIndex 和 putIndex 兩個索引記錄下次拿和新增的位置; 3. 當 takeIndex 和 putIndex 到達數組的最后一個位置時,下次都是從 0 開始循環。 SynchronousQueue 有著兩種數據結構,分別是隊列和堆棧,特征如下: 1. 隊列保證了先入先出的數據結構,體現了公平性; 2. 堆棧是先入后出的數據結構,是不公平的,但性能高于先入先出。 #### 1.2 入隊和出隊的方式 不同的隊列有著不同的數據結構,導致其入隊和出隊的方式也不同: 1. 鏈表是入隊是直接追加到隊尾,出隊是從鏈表頭拿數據; 2. 數組是有 takeIndex 和 putIndex 兩個索引位置記錄下次拿和取的位置,如總體設計圖,入隊直接指向了 putIndex,出隊指向了 takeIndex; 3. 堆棧主要都是圍繞棧頭進行入棧和出棧的。 #### 1.3 生產者和消費者之間的通信機制 從四種隊列我們可以看出來生產者和消費者之間有兩種通信機制,一種是強關聯,一種是無關聯。 強關聯主要是指 SynchronousQueue 隊列,生產者往隊列中 put 數據,如果這時候沒有消費者消費的話,生產者就會一直阻塞住,是無法返回的;消費者來隊列里取數據,如果這時候隊列中沒有數據,消費者也會一直阻塞住,所以 SynchronousQueue 隊列模型中,生產者和消費者是強關聯的,如果只有其中一方存在,只會阻塞,是無法傳遞數據的。 無關聯主要是說有數據存儲功能的隊列,比如說 LinkedBlockingQueue 和 ArrayBlockingQueue,只要隊列容器不滿,生產者就能放成功,生產者就可以直接返回,和有無消費者一點關系都沒有,生產者和消費者完全解耦,通過隊列容器的儲存功能進行解耦。 ### 2 工作中的使用場景 在日常工作中,我們需要根據隊列的特征來匹配業務場景,從而決定使用哪種隊列,我們總結下各個隊列適合使用的場景: #### 2.1 LinkedBlockingQueue 適合對生產的數據大小不定(時高時低),數據量較大的場景,比如說我們在淘寶上買東西,點擊下單按鈕時,對應著后臺的系統叫做下單系統,下單系統會把下單請求都放到一個線程池里面,這時候我們初始化線程池時,一般會選擇 LinkedBlockingQueue,并且設置一個合適的大小,此時選擇 LinkedBlockingQueue 主要原因在于:在不高于我們設定的閾值內,隊列里面的大小可大可小,不會有任何性能損耗,正好符合下單流量的特點,時大時小。 一般工作中,我們大多數都會選擇 LinkedBlockingQueue 隊列,但會設置 LinkedBlockingQueue 的最大容量,如果初始化時直接使用默認的 Integer 的最大值,當流量很大,而消費者處理能力很差時,大量請求都會在隊列中堆積,會大量消耗機器的內存,就會降低機器整體性能甚至引起 宕機,一旦宕機,在隊列中的數據都會消失,因為隊列的數據是保存在內存中的,一旦機器宕機,內存中的數據都會消失的,所以使用 LinkedBlockingQueue 隊列時,建議還是要根據日常的流量設置合適的隊列的大小。 #### 2.2 ArrayBlockingQueue 一般用于生產數據固定的場景,比如說系統每天會進行對賬,對賬完成之后,會固定的產生 100 條對賬結果,因為對賬結果固定,我們就可以使用 ArrayBlockingQueue 隊列,大小可以設置成 100。 #### 2.3 DelayQueue 延遲隊列,在工作中經常遇到,主要用于任務不想立馬執行,想等待一段時間才執行的場景。 比如說延遲對賬,我們在工作中曾經遇到過這樣的場景:我們在淘寶上買東西,彈出支付寶付款頁面,在我們輸入指紋的瞬間,流程主要是前端 -》交易后端 -》支付后端,交易后端調用支付后端主要是為了把我們支付寶的錢劃給商家,而交易調用支付的過程中,有小概率的情況,因為網絡抖動會發生超時的情況,這時候就需要通過及時的對賬來解決這個事情(對賬只是解決這個 問題的手段之一),我們簡單畫一個流程圖: ![](https://img.kancloud.cn/8e/86/8e86133f53c639567096077cbe8042c7_1184x616.jpg) 這是一個真實場景,為了方便描述,已經大大簡化了,再說明幾點: 1. 交易調用支付的接口,這個接口的作用就是為了把小美的 800 元轉給商家小明; 2. 接口調用超時,此時交易系統并不知道 800 有沒有成功轉給小明,當然想知道的方式有很多,我們選擇了對賬的方式,對賬的目的就是為了知道當前 800 元有沒有成功轉給小明; 3. 延遲對賬的目的,因為支付系統把 800 元轉給商家小明也是需要時間的,如果超時之后立馬對賬,可能轉賬的動作還在進行中,導致對賬的結果不準確,所以需要延遲幾秒后再去對賬; 4. 對賬之后的結果有幾種,比如已經成功的把 800 元轉給小明了,這時候需要把對賬結果告訴交易系統,交易系統更新數據,前端就能夠顯示轉賬成功了。 在這個案列中,延遲對賬的核心技術就是 DelayQueue,我們大概這么做的:新建對賬任務,設置 3 秒之后執行,把任務放到 DelayQueue 中,過了 3 秒之后,就會自動執行對賬任務了。 DelayQueue 延遲執行的功能就在這個場景中得到應用。 #### 3 總結 我們不會為了閱讀源碼而讀源碼,我們讀源碼的最初目的,是為了提高我們的技術深度,最終目的是為了在不同的場景中,能夠選擇合適的技術進行落地,本章中解釋的一些隊列的場景,我們在工作中其實都會遇到,特別是在使用線程池時,使用哪種隊列是我們必須思考的一個問題,所以本章先比較了各個隊列的適合使用場景,然后舉了幾個案列進行具體分析,希望大家也能把技術具體落地到實際工作中,使技術推動、輔助業務。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看