1. 程式人生 > >《Java程式效能優化 讓你的Java程式更快、更穩定》閱讀筆記

《Java程式效能優化 讓你的Java程式更快、更穩定》閱讀筆記

一.Linux中常用的監控CPU整體效能的工具有:

§ mpstat: mpstat 不但能檢視所有CPU的平均資訊,還能檢視指定CPU的資訊。

               mpstat [-P {|ALL}] [internal [count]]  -P {|ALL} 表示監控哪個CPU, cpu在[0,cpu個數-1]中取值

§ vmstat:只能檢視所有CPU的平均資訊;檢視cpu佇列資訊; 

               vmstat和sar類似也可指定取樣週期和取樣數量

§ iostat: 只能檢視所有CPU的平均資訊,快速定位系統是否產生大量I/O操作

§ sar: 與mpstat 一樣,不但能檢視CPU的平均資訊,還能檢視指定CPU的資訊。

           sar [-u,-r,-b] [<interval> <count>]  -u cpu利用率,-r記憶體利用率,-b I/O利用率,interval表示取樣週期,count表示取樣數量

§ top:顯示的資訊同ps接近,但是top可以瞭解到CPU消耗,可以根據使用者指定的時間來更新顯示。

pidstat  linux效能檢測工具

      在Debian/Ubuntu系統中可以使用下面的命令來安裝

  # apt-get install sysstat

  CentOS/Fedora/RHEL版本的linux中則使用下面的命令:

  # yum install sysstat


二.RPC和Http的區別:

目前有很多Java的RPC框架,有基於Json的,有基於XML,也有基於二進位制物件的。

論複雜度,RPC框架肯定是高於簡單的HTTP介面的。但毋庸置疑,HTTP介面由於受限於HTTP協議,需要帶HTTP請求頭,導致傳輸起來效率或者說安全性不如RPC。

現在問題是,遇到怎樣的瓶頸了才需要或者說更適合用RPC(比如像阿里這麼大的請求併發量,簡單的HTTP肯定達不到預期),但問題是大家所在的公司,要有像阿里這麼大的量是比較少的,甚至說1/1000的量可能都沒有,那我們還需要使用RPC嗎?

技術應該不是為了使用新技術而去使用,而應該是舊技術存在某些瓶頸,存在難以支撐或者擴充套件性越老越差等問題暴露出來之後,用新技術來進行解決。


http介面是在介面不多、系統與系統互動較少的情況下,解決資訊孤島初期常使用的一種通訊手段;優點就是簡單、直接、開發方便。利用現成的http協議進行傳輸。但是如果是一個大型的網站,內部子系統較多、介面非常多的情況下,RPC框架的好處就顯示出來了,首先就是長連結,不必每次通訊都要像http一樣去3次握手什麼的,減少了網路開銷;其次就是RPC框架一般都有註冊中心,有豐富的監控管理;釋出、下線介面、動態擴充套件等,對呼叫方來說是無感知、統一化的操作。第三個來說就是安全性。最後就是最近流行的服務化架構、服務化治理,RPC框架是一個強力的支撐

三.NIO的理解

3.1NIO和BIO的區別和各自適用的場景

區別:
BIO:同步阻塞式IO,伺服器實現模式為一個連線一個執行緒,即客戶端有連線請求時伺服器端就需要啟動一個執行緒進行處理,如果這個連線不做任何事情會造成不必要
的執行緒開銷,當然可以通過執行緒池機制改善。
NIO:同步非阻塞式IO,伺服器實現模式為一個請求一個執行緒,即客戶端傳送的連線請求都會註冊到多路複用器上,多路複用器輪詢到連線有I/O請求時才啟動一個執行緒
進行處理。

各自應用場景:
NIO適合處理連線數目特別多,但是連線比較短(輕操作)的場景,Jetty,Mina,ZooKeeper等都是基於java nio實現。
BIO方式適用於連線數目比較小且固定的場景,這種方式對伺服器資源要求比較高,併發侷限於應用中。

3.2給我們帶來了些什麼

事件驅動模型
避免多執行緒
單執行緒處理多工
非阻塞I/O,I/O讀寫不再阻塞,而是返回0
基於block的傳輸,通常比基於流的傳輸更高效

更高階的IO函式,zero-copyIO多路複用大大提高了Java網路應用的可伸縮性和實用性

NIO一個重要的特點是:socket主要的讀、寫、註冊和接收函式,在等待就緒階段都是同步非阻塞的,真正的I/O操作是同步阻塞的(消耗CPU但效能非常高)。

解釋的比較清楚的文章:


四常用的集合

ArrayList的內部實現是基於基礎的物件陣列的,因此,它使用get方法訪問列表中的任意一個元素時(random-access),它的速度要比LinkedList快


LinkedList基於連結串列的資料結構沒有同步辦法。若是多個執行緒同時接見一個List,則必須本身實現接見同步。一種解決辦法是在建立List機會關一個同步的List:
List list = Collections.synchronizedList(new LinkedList(...));

Vector是同步的。由Vector建立的Iterator,固然和ArrayList建立的Iterator是同一介面,然則,因為Vector是同步的,當一個Iterator被建立並且正在被應用,另一個執行緒改變了Vector的狀況(例如,新增或刪除了一些元素),這時呼叫Iterator的辦法時將丟擲ConcurrentModificationException,是以必須捕獲該異常。

總結特點如下:

型別 內部結構 順序遍歷速度 隨機遍歷速度 追加代價 插入代價 刪除代價 佔用記憶體
ArrayList 陣列
LinkedList 雙向連結串列

所以:
  • 一般順序遍歷情況下使用ArrayList,但注意建構函式中設定初始大小
  • 儘量不對ArrayList進行插入或刪除操作(刪除尾部除外),若有多次刪除/插入操作又有隨機遍歷的需求,可以再構建一個ArrayList,把複合條件的物件放入新ArrayList,而不要頻繁操作原ArrayList
  • 經常有刪除/插入操作而順序遍歷列表的情況下最適合使用LinkedList

五鎖

只在REPEATABLE READ或以上的隔離級別下的特定操作才會取得gap lock或nextkey lock。