前面的內(nèi)容把雪花算法的時間部分和機(jī)器信息部分都生成了芽突,下面來生成最后一部分,就是毫秒內(nèi)的序列族吻。什么意思呢急灭?我們在生成時間部分獲取時間戳的時候姐浮,使用 long now = System.currentTimeMillis(); 獲取,是個毫秒級的時間戳葬馋,但是即使是這么短的時間卖鲤,對于電腦來說也足夠生成很多個id,所以很多id可能會在同一個毫秒內(nèi)生成畴嘶,也就是時間部分的數(shù)值一樣蛋逾。這個時候就要讓同一個毫秒內(nèi)生成的id加上數(shù)字序列標(biāo)識,就是第三部分的序列窗悯。第三部分占的長度是12位区匣,轉(zhuǎn)成整數(shù)值就是4095,所以最后一部分的范圍就是4095到0之間的數(shù)字蒋院。如果毫秒內(nèi)訪問的數(shù)量超過了這個限制怎么辦沉颂?沒法解決,只能強(qiáng)制等到下一毫秒再生產(chǎn)id悦污。這就是第三部分的作用。
下面先定義一個序列初始值:
序列由于和時間戳有關(guān)系钉蒲,所以要加載時間戳真正開始使用之前:
上面的邏輯做了判斷切端,同一毫秒內(nèi)就讓序列加1,超過4095顷啼,就強(qiáng)制獲取下一毫秒的值踏枣,等時間戳不是同一毫秒的時候,序列從新開始計算钙蒙∫鹌伲看下如何強(qiáng)制獲取下一毫秒:
簡單粗暴,就是while循環(huán)等下一毫秒就可以躬厌。這樣毫秒內(nèi)的序列數(shù)就算獲取成功了马昨。
我們?nèi)蟛糠值臄?shù)字都獲取成功了,最后直接位移加合并就行:
這樣雪花算法就寫完了,下面執(zhí)行一下測試:
是一個18位的long類型數(shù)字鸿捧,確實是我們要的結(jié)果屹篓。等等!是不是有問題匙奴?如果此時多個線程訪問堆巧,會產(chǎn)生重復(fù)的id!現(xiàn)在的程序確實有多并發(fā)問題泼菌,需要加上鎖:
這樣我們的雪花算法算是初步完成了谍肤。基本也符合項目對唯一id的要求哗伯!現(xiàn)在的寫法和網(wǎng)上的例子還有些差別荒揣,下面我們講講差別相關(guān)的內(nèi)容。