前面的內容把雪花算法的時間部分和機器信息部分都生成了,下面來生成最后一部分,就是毫秒內的序列。什么意思呢?我們在生成時間部分獲取時間戳的時候,使用 long now = System.currentTimeMillis(); 獲取,是個毫秒級的時間戳,但是即使是這么短的時間,對於電腦來說也足夠生成很多個id,所以很多id可能會在同一個毫秒內生成,也就是時間部分的數值一樣。這個時候就要讓同一個毫秒內生成的id加上數字序列標識,就是第三部分的序列。第三部分占的長度是12位,轉成整數值就是4095,所以最后一部分的范圍就是4095到0之間的數字。如果毫秒內訪問的數量超過了這個限制怎么辦?沒法解決,只能強制等到下一毫秒再生產id。這就是第三部分的作用。
下面先定義一個序列初始值:

序列由於和時間戳有關系,所以要加載時間戳真正開始使用之前:

上面的邏輯做了判斷,同一毫秒內就讓序列加1,超過4095,就強制獲取下一毫秒的值,等時間戳不是同一毫秒的時候,序列從新開始計算。看下如何強制獲取下一毫秒:

簡單粗暴,就是while循環等下一毫秒就可以。這樣毫秒內的序列數就算獲取成功了。
我們三大部分的數字都獲取成功了,最后直接位移加合並就行:

這樣雪花算法就寫完了,下面執行一下測試:

是一個18位的long類型數字,確實是我們要的結果。等等!是不是有問題?如果此時多個線程訪問,會產生重復的id!現在的程序確實有多並發問題,需要加上鎖:

這樣我們的雪花算法算是初步完成了。基本也符合項目對唯一id的要求!現在的寫法和網上的例子還有些差別,下面我們講講差別相關的內容。