自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何編寫高性能Java程序的技術(shù)匯編?

新聞
性能并不總是我們需要首要考慮的因素,但當(dāng)我們需要處理的數(shù)據(jù)量較大,或者對(duì)象、計(jì)算需要消耗較多資源時(shí),性能問題就會(huì)自然浮上來,需要我們花些心思進(jìn)行調(diào)優(yōu)。

本文搜集整理了40多條編寫高性能Java代碼的心法,希望可以幫到您。

1.清理代碼并修改算法

不斷地重構(gòu)和整理代碼,去除算法中冗余的步驟,使代碼更加可讀和精煉的同時(shí),通過避免額外的計(jì)算來提升性能。

2.盡量指定類、方法為final

Java編譯器會(huì)盡量將final的方法內(nèi)聯(lián)化,從而大幅提升性能(約50%)。所以,如可能,盡量將對(duì)類、方法使用final修飾符。

3.避免濫用靜態(tài)變量

如無必要,避免將成員申明為static,否則可能導(dǎo)致該成員持有的對(duì)象一直不會(huì)被釋放,直到程序終止或修改引用。

4.保持方法簡短

過大的方法將消耗更多的內(nèi)存和CPU周期,而短小精悍的方法將帶來更好的內(nèi)聚性、可讀性,和更小的內(nèi)存占用,從而帶來更好的性能。嘗試在適當(dāng)?shù)倪壿孅c(diǎn),將過大的方法拆分為合適的小方法。

5.避免使用遞歸

遞歸是一種很好的算法,有切實(shí)的好處和實(shí)際用途,但是遞歸本身具有較高的運(yùn)行成本。如果性能成為問題,可以考慮放棄遞歸,改用循環(huán)。

6.避免濫用異常

拋出異常需要?jiǎng)?chuàng)建對(duì)象、獲取堆棧等較重開銷,異常只用來處理錯(cuò)誤,不要刻意用于控制運(yùn)行流程。

7.盡量使用局部變量

調(diào)用方法傳入的參數(shù)、方法創(chuàng)建的臨時(shí)變量等局部變量都存于棧中,訪問時(shí)比存于堆中的靜態(tài)變量、實(shí)例變量要快,而且也會(huì)隨著方法調(diào)用結(jié)束而被快速清理掉。

8.減少對(duì)變量的重復(fù)計(jì)算

調(diào)用方法存在一定成本,如創(chuàng)建棧幀、保護(hù)現(xiàn)場(chǎng)、恢復(fù)現(xiàn)場(chǎng)等,所以,如果變量只需計(jì)算一次,就可以提前計(jì)算好,不要重復(fù)計(jì)算,減少方法調(diào)用。

9.盡量使用基礎(chǔ)類型

將數(shù)據(jù)存儲(chǔ)在棧,而不是堆上,有利于更快地回收內(nèi)存空間,更快地訪問數(shù)據(jù)。因此,盡量使用基礎(chǔ)類型(如int),而不是包裝類型(Integer),有助于降低內(nèi)存消耗,提升性能。

如果可能,盡量使用array,而不是ArrayList。

10.避免使用BigInteger和BigDecimal

BigInteger和BigDecimal提供了更高的計(jì)算精度,但是也會(huì)占用更多的內(nèi)存和CPU,如果允許的話,使用Long和Double作為替代。

11.使用isEmpty檢查String是否為空

String是一個(gè)byte數(shù)組,isEmpty會(huì)判斷數(shù)組的length,很快就能獲得結(jié)果。

12.對(duì)于單字符,使用char類型,而不是String

在處理單個(gè)字符的字符串時(shí),使用char以獲得更好的性能。

13.使用更輕量級(jí)運(yùn)算

必要時(shí),乘除運(yùn)算可使用更輕量的位移運(yùn)算替代。

14.避免Random實(shí)例被多線程使用

多線程共用Random實(shí)例時(shí),容易因競爭seed而性能下降,可以使用ThreadLocalRandom作為替代。

15.使用StringBuilder拼接字符串

使用+號(hào)拼接字符串,可能會(huì)創(chuàng)建過多的字符串對(duì)象。而StringBuffer有同步機(jī)制,性能不及StringBuilder,但要注意StringBuilder是線程不安全的。

在單個(gè)語句中使用+連接長字符串,以提升可讀性,也是可以被編譯器優(yōu)化的。

避免在循環(huán)體中使用+拼接字符串,這樣可能會(huì)導(dǎo)致創(chuàng)建過多的StringBuilder對(duì)象。

16.更好地替換字符串

在Java8及以下版本中,使用Apache Commons StringUtils.replace來替換字符串,比JDK原生的String.replace高效,而更高版本的Java,則使用String.replace會(huì)更好。

17.避免過多if-else語句

在代碼中,尤其是循環(huán)體中過多地使用if-else語句,將迫使JVM比較這些條件,從而消耗性能。如果業(yè)務(wù)邏輯中的判斷條件過多,可嘗試通過分組并計(jì)算boolean結(jié)果,再在if語句中使用它。

18.盡可能復(fù)用已有對(duì)象,而不是隨意創(chuàng)建

創(chuàng)建新對(duì)象有一定的成本,尤其是大量創(chuàng)建的情況下。如果可以,盡量復(fù)用已有對(duì)象,甚至使用單例模式,而不是隨意創(chuàng)建新的對(duì)象,尤其是那些大的對(duì)象。

如果存在較多的重復(fù)字符串,可以考慮創(chuàng)建這些字符串對(duì)象時(shí)使用String.intern方法,將字符串放入常量池,再次創(chuàng)建時(shí)從常量池獲取同一對(duì)象,以減少內(nèi)存占用。

在滿足某些條件時(shí),才使用的對(duì)象,可以考慮延遲到進(jìn)入條件區(qū)時(shí)再創(chuàng)建,而不是提早創(chuàng)建。

避免在循環(huán)中聲明和創(chuàng)建對(duì)象,創(chuàng)建過多的對(duì)象引用,可以把聲明拿到循環(huán)之前。

19.盡量使用indexOf,而不是split分割字符串

String的split方法中使用了功能更強(qiáng)大的正則表達(dá)式,但正則表達(dá)式的性能并不總是好,使用不當(dāng)會(huì)導(dǎo)致回溯問題,使CPU居高不下。所以,除非回溯問題可控,盡量使用indexOf來分割字符串。

在任何時(shí)候使用正則表達(dá)式時(shí),都要盡量采用獨(dú)占模式,避免使用貪婪模式,避免分支選擇,避免捕獲組的嵌套等,以避免性能問題。

20.選擇合適的集合類型

ArrayList、HashMap不是線程安全的,而Vector、Hashtable是線程安全的同步集合。當(dāng)在多線程環(huán)境下可能需要線程安全的集合,而不需要線程同步時(shí),盡量使用ArrayList、HashMap,以獲得多倍的性能提升。

ArrayList和LinkedList分別基于數(shù)組和鏈表實(shí)現(xiàn),兩者的利用迭代器遍歷(含foreach)的性能相當(dāng),但使用for循環(huán)遍歷時(shí),ArrayList因?yàn)橛锌焖匐S機(jī)訪問的特性,性能要高于LinkedList。另外,在ArrayList不發(fā)生擴(kuò)容的情況下,在尾部添加刪除元素的性能要略高于LinkedList,而LinkedList在頭部添加元素的性能較ArrayList高。

21.在構(gòu)造時(shí)初始化集合

如果集合內(nèi)元素可在初始化時(shí)確定,則盡量在集合對(duì)象構(gòu)造時(shí)初始化進(jìn)去,而不是先實(shí)例化集合對(duì)象,再一個(gè)一個(gè)將元素添加進(jìn)去。

22.高效使用HashMap

在已知數(shù)據(jù)量的情況下,提前設(shè)置初始容量(數(shù)據(jù)量 ÷ 加載因子),避免擴(kuò)容開銷。

一般使用默認(rèn)的加載因子(0.75)即可,當(dāng)特別要求充分利用內(nèi)存資源時(shí),可增大加載因子,而當(dāng)查詢類操作頻繁時(shí),可考慮縮減加載因子。

23.不要在循環(huán)中獲取集合的大小

如果要遍歷集合,那么就提前獲取集合的長度,而不是在循環(huán)中每次判斷集合的大小。

24.盡量減少集合方法的調(diào)用次數(shù)

集合提供了很多好用的方法,如size()、containsKey()等,如有可能,盡量減少和避免調(diào)用這些方法

25.使用addAll,而不是add

addAll可以筆add擁有每秒更高的操作數(shù),如果可以,在向ArrayList這種集合添加多個(gè)元素時(shí),盡量使用addAll批量添加,而不是通過add方法逐個(gè)添加。

26.使用entrySet,而不是keySet

EntrySet 可以在一秒鐘內(nèi)比 KeySet 多運(yùn)行 9000 個(gè)操作,所以在遍歷HashMap時(shí),盡量使用entrySet,而不是keySet。

27.使用singletonList構(gòu)造單元素集合

使用singletonList生成單元素集合,比用構(gòu)造函數(shù)new一個(gè)更好。

28.使用EnumSet,而不是HashSet

如果Set中存儲(chǔ)的時(shí)枚舉值(Enum),則最好使用EnumSet,以獲得更好的性能。

29.謹(jǐn)慎使用ArrayList的contains方法

集合大都有一個(gè)contains方法,用于判斷元素是否已存在于集合中。但是,當(dāng)ArrayList、Vector這種集合數(shù)據(jù)量較大時(shí),此方法在最差情況下將遍歷整個(gè)集合,如果在循環(huán)中使用,將帶來巨大的性能開銷。因此,當(dāng)需要在大型數(shù)據(jù)集中搜索時(shí),可考慮使用HashMap替代ArrayList。

30.必要時(shí)使用Stream遍歷集合

通常,在數(shù)量量少、循環(huán)次數(shù)較少,以及應(yīng)用在單核運(yùn)行的情況下,常規(guī)迭代遍歷集合的性能較高。如果在多核環(huán)境下,對(duì)大數(shù)據(jù)量集合進(jìn)行迭代,則可以考慮使用由并行機(jī)制的Stream。

31.必要時(shí)使用NIO

傳統(tǒng)I/O類在高并發(fā)、大數(shù)據(jù)場(chǎng)景下容易發(fā)生阻塞,而且數(shù)據(jù)在內(nèi)核空間和用戶空間的復(fù)制也存在性能開銷。一般的場(chǎng)景,可通過Buffer解決阻塞問題,而性能要求更高時(shí),就需要引入NIO,通過DirectBuffer、Channel、多路復(fù)用等提升性能。

32.必要時(shí)使用高性能通信協(xié)議

通常,在需要高性能的分布式環(huán)境中,應(yīng)用服務(wù)間調(diào)用會(huì)采用RPC通信框架,而RMI這種較早的RPC通信方式因序列化性能差、阻塞式I/O、短連接等弊病導(dǎo)致性能不能滿足需要。為此,可改為使用Dubbo這種在各方面優(yōu)化過的通信協(xié)議,以滿足高并發(fā)、小對(duì)象傳輸需要。

33.必要時(shí)使用序列化框架

Java原生的序列化性能較差,如有必要,可使用Protobuf、FastJson、Kryo等序列化框架進(jìn)行安全、高效地序列化。

34.謹(jǐn)慎使用字符串作為同步對(duì)象

JVM會(huì)緩存字符串對(duì)象,不同地方聲明的String,如果未使用new String,則可能指向同一個(gè)字符串對(duì)象,如果使用它作為同步對(duì)象,則可能產(chǎn)生意想不到的后果。另外,作為一條通用規(guī)則,請(qǐng)盡量保持同步塊內(nèi)的處理量為最低限度,以提升性能。

35.多線程調(diào)優(yōu)技術(shù)

對(duì)于多線程運(yùn)行的代碼,可考慮以下調(diào)優(yōu)方法:

  1. 在邏輯簡單、運(yùn)算較快的情況下優(yōu)先考慮單線程模式,而耗時(shí)的復(fù)雜計(jì)算則可以考慮多線程并發(fā)
  2. 降低鎖的粒度,縮小同步塊,分離讀寫鎖,最小化鎖的持有時(shí)間,以減少鎖競爭,提升自旋鎖成功率,降低升級(jí)為重量級(jí)鎖的可能性
  3. 僅需要保障可見性、有序性時(shí),可使用開銷較小的volatile關(guān)鍵字,避免上下文切換
  4. 設(shè)置合理的線程池大小,避免過多線程的上下文切換開銷
  5. 適時(shí)使用并發(fā)容器類,對(duì)數(shù)據(jù)有強(qiáng)一致性要求時(shí),可使用Hashtable、Vector等強(qiáng)一致性容器,而讀遠(yuǎn)大于寫時(shí)可使用CopyOnWriteArrayList,當(dāng)數(shù)據(jù)量較小、查詢頻繁時(shí),可使用ConcurrentHashMap容器類。

36.輸出前檢查日志級(jí)別

在輸出某個(gè)級(jí)別的日志之前,先檢查該級(jí)別是否開啟,以避免額外的計(jì)算。

37.避免將大對(duì)象輸出到日志中

在將對(duì)象輸出到日志時(shí),僅選取關(guān)鍵的屬性作為輸出,避免將整個(gè)大對(duì)象都序列化輸出。

38.緩存昂貴的資源

創(chuàng)建對(duì)象有性能開銷,有些對(duì)象(如數(shù)據(jù)庫連接)的創(chuàng)建過程尤其耗時(shí),而有些對(duì)象本身則占用較大資源,將這些對(duì)象緩存起來以便再次使用,而不是隨意創(chuàng)建,將大大提升性能。

如果可以,盡量使用類似Integer.valueOf方法復(fù)用內(nèi)存中已有對(duì)象,而不是用new Integer創(chuàng)建新的對(duì)象,尤其是需要大量這種對(duì)象的時(shí)候。

但是,需要注意,緩存需要額外進(jìn)行管理,如果合算才使用。

39.使用預(yù)編譯的SQL語句

預(yù)編譯語句(PreparedStatement)具有編譯一次而多次使用的特點(diǎn),比起普通Statement有更好的性能。預(yù)編譯語句也是安全的,可以避免SQL注入。

40.只選取需要的數(shù)據(jù)列,而不是*

SELECT語句中,只返回那些需要的列,可以節(jié)省網(wǎng)絡(luò)帶寬,帶來更好的性能。

41.使用正確的表聯(lián)接

當(dāng)需要從多個(gè)表關(guān)聯(lián)查詢數(shù)據(jù)時(shí),注意使用正確的表聯(lián)接方式,并在聯(lián)接字段上建立必要的索引。

42.使用聯(lián)接,而不是子查詢

相對(duì)于聯(lián)接只遍歷一次數(shù)據(jù),子查詢會(huì)多次遍歷數(shù)據(jù),比聯(lián)接耗費(fèi)更多的時(shí)間。

43.使用存儲(chǔ)過程,而不是查詢

如果查詢語句過于復(fù)雜而冗長,則考慮改為使用數(shù)據(jù)庫存儲(chǔ)過程,以獲得存儲(chǔ)過程預(yù)編譯、較少的數(shù)據(jù)傳遞等帶來的性能。

責(zé)任編輯:華軒 來源: 今日頭條
相關(guān)推薦

2024-03-20 08:00:00

軟件開發(fā)Java編程語言

2014-04-25 09:02:17

LuaLua優(yōu)化Lua代碼

2015-12-17 13:19:29

編寫高性能Swift

2018-01-12 14:37:34

Java代碼實(shí)踐

2014-11-25 10:03:42

JavaScript

2012-12-17 13:51:22

Web前端JavaScriptJS

2009-06-24 15:00:39

Javascript代

2011-03-11 09:51:47

Java NIO

2011-04-07 09:18:59

MySQL語法

2022-02-24 09:00:38

React代碼模式

2012-02-13 16:09:40

Java

2015-04-27 14:42:24

技術(shù)架構(gòu)服務(wù)器性能

2023-10-12 09:00:00

AerospikeRedpanda高性能

2012-09-11 11:08:23

Github系統(tǒng)

2017-12-05 08:41:14

高性能存儲(chǔ)產(chǎn)品

2019-08-26 18:20:05

JavascriptWeb前端

2023-10-31 18:52:29

網(wǎng)絡(luò)框架XDP技術(shù)

2019-04-08 10:09:04

CPU緩存高性能

2024-09-06 07:55:42

2017-12-07 13:40:00

JavaScript內(nèi)存泄露內(nèi)存管理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)