<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                38.2 對象池模式 上周二,師兄過來找我,他負責運維一個大型新聞網站,說是網站出現性能,讓我幫忙分析調優。我這幾天正好閑得手癢,同時又賣個人情,何樂而不為呢。于是我們倆就到機房蹲點,追查問題。 38.2.1 正確的池化 簡單說明一下該系統的場景,這是一個專業的新聞追蹤網站,關注的是專業新聞的深度,在行業內具有相當大的影響力。最近一段時間內出現偶發性緩慢,從監控情況上看,響應時間在2秒以上,由于最近軟硬件環境都沒有變更過,因此直覺判斷:最快捷、直觀的解決方案就是增加DB硬件設備。但由于東家是窮慣了,不同意在沒有徹查問題之前而依靠增強硬件來解決問題,于是我們這些軟件工程師就忙活起來了。 網站首頁內容基本都是靜態的(輪詢生成),唯一的動態部分是網站的激勵語,比如“積一時之跬步,臻千里之遙程”、“業精于勤,荒于嬉;行成于思,毀于隨”等勵志語句,這是一個簡單的SQL隨機查詢結果,表中的數量在5000條左右,而且結構簡單,查詢性能不是問題。示例代碼如代碼清單38-29所示。 代碼清單38-29 無緩存的SQL隨機讀取 @Service public?class?WisdomProvider?{ ????????@Autowire ????????private?WisdomDao?wisdomDao; ????????public?String?getOneWord()?{ ????????????????return?wisdomDao.randomOneWisdom(); ????????} } 對于代碼中的@Service、@Autowire注解,做過Spring開發的都懂,這是一個典型的三層架構,WisdomDao的randomOneWisdom方法是通過數據庫隨機函數查詢一條記錄。在跟蹤過程中,發現高峰期數據庫連接偶爾出現占滿情況,而且都是查詢該表(順便說下,該數據庫的隨機查詢算法有缺陷),問題找到了:每一次訪問都會直接查詢數據庫,沒有緩存。通常情況下,這沒有問題,但是在高并發的情況下,例如在10萬PV的壓力下服務器基本就垮掉了,這是非常嚴重的問題。 怎么解決呢?好辦,引入一個對象池,把這5000條記錄(根據評估最多不超過20000條記錄)在啟動時直接加載到內存中,在需要時再從內存中取得,以后查詢不再與數據庫交互。示例代碼如代碼清單38-30所示。 代碼清單38-30 增加緩存后的隨機讀取 @Service public?class?WisdomProvider?{ ????????@Autowire ????????private?WisdomDao?wisdomDao; ????????private?List<String>?wisdoms?=?null; ????????@PostConstruct ????????public?void?init()?{ ????????????????wisdoms?=?wisdomDao.getAll(); ????????} ????????public?String?getOneWord()?{ ????????????????return?RandomUtils.getOne(wisdoms); ????????} } @PostConstruct注解的作用是Spring容器在啟動完畢后,直接執行init方法,一次性讀取所有的數據,然后在應用運行期間不再與數據庫交互,直接從List列表中獲取數據。通過這樣的修正,系統性能有了大幅提升,在不增加硬件的情況下,徹底解決了性能問題。這就是對象池模式。 38.2.2 對象池模式的意圖 對象池模式,或者稱為對象池服務,其意圖如下: 通過循環使用對象,減少資源在初始化和釋放時的昂貴損耗[[1]](#)。 注意 這里的“昂貴”可能是時間效益(如性能),也可能是空間效益(如并行處理),在大多的情況下,“昂貴”指性能。 簡單地說,在需要時,從池中提取;不用時,放回池中,等待下一個請求。典型例子是連接池和線程池,這是我們開發中經常接觸到的。類圖如圖38-6所示。 ![](https://box.kancloud.cn/2016-08-14_57b0037257c05.jpg) 圖38-6 對象池模式通用類圖 對象池提供兩個公共的方法:checkOut負責從池中提取對象,checkIn負責把回收對象(當然,很多時候checkIn已經自動化處理,不需要顯式聲明,如連接池),對象池代碼如代碼清單38-31所示。 代碼清單38-31 對象池示例代碼 public?abstract?class?ObjectPool<T>?{ ????????//容器,容納對象 ????????private?Hashtable<T,?ObjectStatus>?pool?=?new?Hashtable<T,?ObjectStatus>(); ????????//初始化時創建對象,并放入到池中 ????????public?ObjectPool()?{ ????????????????pool.put(create(),?new?ObjectStatus()); ????????} ????????//從Hashtable中取出空閑元素 ????????public?synchronized?T?checkOut()?{ ????????????????//這是最簡單的策略 ????????????????for?(T?t?:?pool.keySet())?{ ????????????????????????if?(pool.get(t).validate())?{ ????????????????????????????????pool.get(t).setUsing(); ????????????????????????????????return?t; ????????????????????????} ????????????????} ????????????????return?null; ????????} ????????//歸還對象 ????????public?synchronized?void?checkIn(T?t)?{ ????????????????pool.get(t).setFree(); ????????} ????????class?ObjectStatus?{ ????????????????//占用 ????????????????public?void?setUsing()?{ ????????????????} ????????????????//釋放 ????????????????public?void?setFree()?{ ????????????????????????//注意:若T是有狀態,則需要回歸到初始化狀態 ????????????????} ????????????????//檢查是否可用 ????????????????public?boolean?validate()?{ ????????????????????????return?false; ????????????????} ????????} ????????//創建池化對象 ????????public?abstract?T?create(); } 這是一個簡單的對象池實現,在實際應用中還需要考慮池的最小值、最大值、池化對象狀態(若有的話,需要重點考慮)、異常處理(如滿池情況)等方面,特別是池化對象狀態,若是有狀態的業務對象則需要重點關注。 38.2.3 最佳實踐 把對象池化的本意是期望一次性初始化所有對象,減少對象在初始化上的昂貴性能開銷,從而提高系統整體性能。然而池化處理本身也要付出代價,因此,并非任何情況下都適合采用對象池化。 通常情況下,在重復生成對象的操作成為影響性能的關鍵因素時,才適合進行對象池化。但是若池化所能帶來的性能提高并不顯著或重要的話,建議放棄對象池化技術,以保持代碼的簡明,轉而使用更好的硬件來提高性能為佳。 對象池技術在Java領域已經非常成熟,只要做過企業級開發的人員,基本都用過C3P0、DBCP、Proxool等連接池,也配置過minPoolSize、maxPoolSize等參數,這是對象池模式的典型應用。在實際開發中若需要對象池,建議使用common-pool工具包來實現,簡單、快捷、高效。 [[1]](#)原文是Avoid expensive acquisition and release of resources by recycling objects that are no longer in use。
                  <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>

                              哎呀哎呀视频在线观看