国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務(wù)器之家 - 編程語言 - JAVA教程 - JDK源碼中一些實用的“小技巧”總結(jié)

JDK源碼中一些實用的“小技巧”總結(jié)

2021-04-16 13:08方老司 JAVA教程

這篇文章主要給大家總結(jié)介紹了關(guān)于JDK源碼中一些實用的“小技巧”,文中通過示例代碼介紹的非常詳細,對大家學習或者使用jdk源碼具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。

前言

這段時間比較閑,就看起了jdk源碼。一般的一個高級開發(fā)工程師, 能閱讀一些源碼對自己的提升還是蠻大的。本文總結(jié)了一些JDK源碼中的“小技巧”,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。

1 i++ vs i--

String源碼的第985行,equals方法中

?
1
2
3
4
5
while (n--!= 0) {
 if (v1[i] != v2[i])
  return false;
 i++;  
}

這段代碼是用于判斷字符串是否相等,但有個奇怪地方是用了i--!=0來做判斷,我們通常不是用i++么?為什么用i--呢?而且循環(huán)次數(shù)相同。原因在于編譯后會多一條指令:

i-- 操作本身會影響CPSR(當前程序狀態(tài)寄存器),CPSR常見的標志有N(結(jié)果為負), Z(結(jié)果為0),C(有進位),O(有溢出)。i > 0,可以直接通過Z標志判斷出來。

i++操作也會影響CPSR(當前程序狀態(tài)寄存器),但只影響O(有溢出)標志,這對于i < n的判斷沒有任何幫助。所以還需要一條額外的比較指令,也就是說每個循環(huán)要多執(zhí)行一條指令。

簡單來說,跟0比較會少一條指令。所以,循環(huán)使用i--,高端大氣上檔次。

2 成員變量 vs 局部變量

JDK源碼在任何方法中幾乎都會用一個局部變量來接受成員變量,比如

?
1
2
3
public int compareTo(String anotherString) {
  int len1 = value.length;
  int len2 = anotherString.value.length;

因為局部變量初始化后是在該方法線程棧中,而成員變量初始化是在堆內(nèi)存中,顯然前者更快,所以,我們在方法中盡量避免直接使用成員變量,而是使用局部變量。

3 刻意加載到寄存器 && 將耗時操作放到鎖外部

在ConcurrentHashMap中,鎖segment的操作很有意思,它不是直接鎖,而是類似于自旋鎖,反復(fù)嘗試獲取鎖,并且在獲取鎖的過程中,會遍歷鏈表,從而將數(shù)據(jù)先加載到寄存器中緩存中,避免在鎖的過程中在便利,同時,生成新對象的操作也是放到鎖的外部來做,避免在鎖中的耗時操作

?
1
2
3
4
5
final V put(K key, int hash, V value, boolean onlyIfAbsent) {
  /** 在往該 segment 寫入前,需要先獲取該 segment 的獨占鎖
    不是強制lock(),而是進行嘗試 */
  HashEntry<K,V> node = tryLock() ? null :
    scanAndLockForPut(key, hash, value);

scanAndLockForPut()源碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private HashEntry<K,V> scanAndLockForPut(K key, int hash, V value) {
  HashEntry<K,V> first = entryForHash(this, hash);
  HashEntry<K,V> e = first;
  HashEntry<K,V> node = null;
  int retries = -1; // negative while locating node
 
  // 循環(huán)獲取鎖
  while (!tryLock()) {
    HashEntry<K,V> f; // to recheck first below
    if (retries < 0) {
      if (e == null) {
        if (node == null) // speculatively create node
          //該hash位無值,新建對象,而不用再到put()方法的鎖中再新建
          node = new HashEntry<K,V>(hash, key, value, null);
        retries = 0;
      }
      //該hash位置key也相同,退化成自旋鎖
      else if (key.equals(e.key))
        retries = 0;
      else
        // 循環(huán)鏈表,cpu能自動將鏈表讀入緩存
        e = e.next;
    }
    // retries>0時就變成自旋鎖。當然,如果重試次數(shù)如果超過 MAX_SCAN_RETRIES(單核1多核64),那么不搶了,進入到阻塞隊列等待鎖
    //  lock() 是阻塞方法,直到獲取鎖后返回,否則掛起
    else if (++retries > MAX_SCAN_RETRIES) {
      lock();
      break;
    }
    else if ((retries & 1) == 0 &&
         // 這個時候是有大問題了,那就是有新的元素進到了鏈表,成為了新的表頭
         //   所以這邊的策略是,相當于重新走一遍這個 scanAndLockForPut 方法
         (f = entryForHash(this, hash)) != first) {
      e = first = f; // re-traverse if entry changed
      retries = -1;
    }
  }
  return node;
}

4 判斷對象相等可先用==

在判斷對象是否相等時,可先用==,因為==直接比較地址,非??欤鴈quals的話會最對象值的比較,相對較慢,所以有可能的話,可以用a==b || a.equals(b)來比較對象是否相等

5 關(guān)于transient

transient是用來阻止序列化的,但HashMap源碼中內(nèi)部數(shù)組是定義為transient的

?
1
2
3
4
/**
  * The table, resized as necessary. Length MUST Always be a power of two.
  */
 transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

那豈不里面的鍵值對都無法序列化了么,網(wǎng)絡(luò)中用hashmap來傳輸豈不是無法傳輸,其實不然。

Effective Java 2nd, Item75, Joshua大神提到:

For example, consider the case of a hash table. The physical
representation is a sequence of hash buckets containing key-value
entries. The bucket that an entry resides in is a function of the hash
code of its key, which is not, in general, guaranteed to be the same
from JVM implementation to JVM implementation. In fact, it isn't even
guaranteed to be the same from run to run. Therefore, accepting the
default serialized form for a hash table would constitute a serious
bug. Serializing and deserializing the hash table could yield an
object whose invariants were seriously corrupt.

怎么理解? 看一下HashMap.get()/put()知道, 讀寫Map是根據(jù)Object.hashcode()來確定從哪個bucket讀/寫. 而Object.hashcode()是native方法, 不同的JVM里可能是不一樣的.

打個比方說, 向HashMap存一個entry, key為 字符串"STRING", 在第一個java程序里, "STRING"的hashcode()為1, 存入第1號bucket; 在第二個java程序里, "STRING"的hashcode()有可能就是2, 存入第2號bucket. 如果用默認的串行化(Entry[] table不用transient), 那么這個HashMap從第一個java程序里通過串行化導(dǎo)入第二個java程序后, 其內(nèi)存分布是一樣的, 這就不對了.

舉個例子,比如向HashMap存一個鍵值對entry, key="方老司", 在第一個java程序里, "方老司"的hashcode()為1, 存入table[1],好,現(xiàn)在傳到另一個在JVM程序里, "方老司" 的hashcode()有可能就是2, 于是到table[2]去取,結(jié)果值不存在。

HashMap現(xiàn)在的readObject和writeObject是把內(nèi)容 輸出/輸入, 把HashMap重新生成出來.

6 不要用char

char在Java中utf-16編碼,是2個字節(jié),而2個字節(jié)是無法表示全部字符的。2個字節(jié)表示的稱為 BMP,另外的作為high surrogate和 low surrogate 拼接組成由4字節(jié)表示的字符。比如String源碼中的indexOf:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//這里用int來接受一個char,方便判斷范圍
public int indexOf(int ch, int fromIndex) {
   final int max = value.length;
   if (fromIndex < 0) {
     fromIndex = 0;
   } else if (fromIndex >= max) {
     // Note: fromIndex might be near -1>>>1.
     return -1;
   }
   //在Bmp范圍
   if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
     // handle most cases here (ch is a BMP code point or a
     // negative value (invalid code point))
     final char[] value = this.value;
     for (int i = fromIndex; i < max; i++) {
       if (value[i] == ch) {
         return i;
       }
     }
     return -1;
   } else {
     //否則轉(zhuǎn)到四個字節(jié)的判斷方式
     return indexOfSupplementary(ch, fromIndex);
   }
 }

所以Java的char只能表示utf­16中的bmp部分字符。對于CJK(中日韓統(tǒng)一表意文字)部分擴展字符集則無法表示。

例如,下圖中除Ext-A部分,char均無法表示。

JDK源碼中一些實用的“小技巧”總結(jié)

此外還有一種說法是要用char,密碼別用String,String是常量(即創(chuàng)建之后就無法更改),會保存到常量池中,如果有其他進程可以dump這個進程的內(nèi)存,那么密碼就會隨著常量池被dump出去從而泄露,而char[]可以寫入其他的信息從而改變,即是被dump了也會減少泄露密碼的風險。

但個人認為你都能dump內(nèi)存了難道是一個char能夠防范的住的?除非是String在常量池中未被回收,而被其它線程直接從常量池中讀取,但恐怕也是非常罕見的吧。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務(wù)器之家的支持。

原文鏈接:https://segmentfault.com/a/1190000013951261

延伸 · 閱讀

精彩推薦
  • JAVA教程Kotlin教程之基本數(shù)據(jù)類型

    Kotlin教程之基本數(shù)據(jù)類型

    這篇文章主要介紹了Kotlin教程之基本數(shù)據(jù)類型的學習的相關(guān)資料,需要的朋友可以參考下...

    Losileeya2332020-10-26
  • JAVA教程java在文件尾部追加內(nèi)容的簡單實例

    java在文件尾部追加內(nèi)容的簡單實例

    下面小編就為大家?guī)硪黄猨ava在文件尾部追加內(nèi)容的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧 ...

    java教程網(wǎng)2672020-07-11
  • JAVA教程shell腳本運行java程序jar的方法

    shell腳本運行java程序jar的方法

    本篇文章主要介紹了shell腳本運行java程序jar的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    闞壠4742021-01-21
  • JAVA教程MyBatis-Generator的配置說明和使用

    MyBatis-Generator的配置說明和使用

    本文主要介紹了MyBatis-Generator的配置說明和使用的相關(guān)知識。具有很好的參考價值,下面跟著小編一起來看下吧...

    hnlictmso3882020-08-02
  • JAVA教程Java窗體居中顯示的2種方法(實例講解)

    Java窗體居中顯示的2種方法(實例講解)

    下面小編就為大家?guī)硪黄狫ava窗體居中顯示的2種方法(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    Java之家2162020-12-03
  • JAVA教程Java 獲得文件的指紋

    Java 獲得文件的指紋

    在文件上傳到服務(wù)器的時候,我們希望能夠獲得文件的指紋以確定文件沒有被篡改過。常用的算法最開始使用的是 MD5,隨后隨著技術(shù)的發(fā)展,MD5 算法已經(jīng)...

    今日頭條3432020-10-28
  • JAVA教程初步學習Java中線程的實現(xiàn)與生命周期

    初步學習Java中線程的實現(xiàn)與生命周期

    這篇文章主要介紹了初步學習Java中線程的實現(xiàn)與生命周期,線程方面的知識是Java學習過程中的重點和難點,需要的朋友可以參考下 ...

    圣騎士Wind的博客5272020-01-16
  • JAVA教程將Java對象序列化成JSON和XML格式的實例

    將Java對象序列化成JSON和XML格式的實例

    下面小編就為大家分享一篇將Java對象序列化成JSON和XML格式的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    洪墨水8462021-02-28
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 亚洲伊人久久影院 | 久久久久久久久99精品 | av片在线观看 | 中文字幕国产一区 | 欧美日韩一级视频 | 国产成人精品一区二区三区 | 99热精品在线 | 午夜电影网址 | 一级电影在线观看 | 亚洲性片 | 色影视 | 亚洲一区在线视频 | 亚洲精品久久久久中文字幕欢迎你 | 日本不卡免费新一二三区 | 久久精品播放 | 色噜| 中国一级黄色毛片视频 | 久久久久久久国产 | 最近2019中文字幕大全视频10 | 精品久久久av | 国产一区二区三区在线 | 色偷偷888欧美精品久久久 | 91视频在线播放视频 | 在线免费观看av电影 | 日韩素人一区二区三区 | a级毛片免费在线 | 亚洲精品久久久久一区二区三区 | 久久a毛片| 中文字幕三区 | 日韩一区二区三区电影在线观看 | 伊人av在线 | 免费一级欧美在线观看视频 | 91精品国产欧美一区二区成人 | 91cn国产在线 | 99精品国产高清一区二区麻豆 | 青草青草久热精品视频在线观看 | 成人在线免费观看 | 黄色一区二区三区 | 欧美日一区| 91免费看网站 | 欧美日韩在线看 |