java實(shí)現(xiàn)雪花算法ID生成器工具類(lèi)
更新時(shí)間:2023年07月14日 08:33:34 作者:喜羊羊sk
本文主要介紹了java實(shí)現(xiàn)雪花算法ID生成器工具類(lèi),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
IdGenerate
/** * 主鍵(id)生成器,用于生成唯一id號(hào) * 1、注意:在寫(xiě)主鍵生成器時(shí),請(qǐng)考慮主鍵不會(huì)重復(fù)。 * 2、尤其需要考慮在短時(shí)間內(nèi)大量調(diào)用生成器,也保證不要出現(xiàn)重復(fù) * 3、實(shí)現(xiàn)類(lèi)必須是線程安全的,因?yàn)闀?huì)應(yīng)用在多線程環(huán)境中去 * */ @FunctionalInterface public interface IdGenerate<T extends Serializable> { /** * id 生成器 * * @return */ T generate(); }
AbstractIdGenerate
/** ?* 抽象 ID 生成器 ?* ?*/ public abstract class AbstractIdGenerate<T extends Serializable> implements IdGenerate<T> { ? ? private final static int MAX_MACHINE_CODE = 31; ? ? /** ? ? ?* 最大17bit的序列號(hào)是131071 ? ? ?*/ ? ? private final static int MAX_ORDER_NO = 131071; ? ? /** ? ? ?* 時(shí)間戳的掩碼41bit ? ? ?*/ ? ? private final static long TIME_CODE = Long.MAX_VALUE >>> 22; ? ? /** ? ? ?* 2015-01-01 00:00:00 ? ? ?* 1420041600210 ? ? ?* 因?yàn)樯善骺梢允褂?9年,而我們想在這些時(shí)間里面,生成出來(lái)的id是逐漸自增的。 ? ? ?* 所以這里指定了從什么時(shí)候開(kāi)始使用id生成器。 ? ? ?*/ ? ? private final static long START_TIME = 1420041600210L; ? ? /** ? ? ?* 機(jī)器碼 (0-31) ? ? ?*/ ? ? private final long MACHINE_CODE; ? ? /** ? ? ?* 用于生成序列號(hào) ? ? ?*/ ? ? private AtomicInteger orderNo; ? ? public AbstractIdGenerate(final long machineCode) { ? ? ? ? if (machineCode < 0 || machineCode > MAX_MACHINE_CODE) { ? ? ? ? ? ? throw new IllegalArgumentException("請(qǐng)注意,1、機(jī)器碼在多臺(tái)機(jī)器或應(yīng)用間是不允許重復(fù)的!2、機(jī)器碼取值僅僅在0~31之間"); ? ? ? ? } ? ? ? ? this.MACHINE_CODE = machineCode; ? ? ? ? orderNo = new AtomicInteger(0); ? ? } ? ? protected Long generateLong() { ? ? ? ? //1.與基準(zhǔn)時(shí)間對(duì)其,得到相對(duì)時(shí)間 ? ? ? ? long currentTimeMillis = System.currentTimeMillis() - START_TIME; ? ? ? ? //2.保留相對(duì)時(shí)間的低41bit ? ? ? ? currentTimeMillis = currentTimeMillis & TIME_CODE; ? ? ? ? //3、將1到41bit移到高位去 就是23~63。 ? ? ? ? currentTimeMillis = currentTimeMillis << 22; ? ? ? ? /* ? ? ? ? ?* 序列號(hào)自增1和獲取 ? ? ? ? ?* 注意:先增加再取值。 ? ? ? ? ?*/ ? ? ? ? int orderNo = this.orderNo.incrementAndGet(); ? ? ? ? do { ? ? ? ? ? ? if (orderNo > MAX_ORDER_NO) { ? ? ? ? ? ? ? ? //如果超過(guò)了最大序列號(hào) ? 則重置為0 ? ? ? ? ? ? ? ? if (this.orderNo.compareAndSet(orderNo, 0)) { ? ? ? ? ? ? ? ? ? ? //這里使用cas操作,所以不需要加鎖 ? ?1、操作失敗了 ? 則表示別的線程已經(jīng)更改了數(shù)據(jù),則直接進(jìn)行自增并獲取則可以了 ? ? ? ? ? ? ? ? ? ? orderNo = 0; ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? //注意:先增加再取值。 ? ? ? ? ? ? ? ? ? ? orderNo = this.orderNo.incrementAndGet(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } while (orderNo > MAX_ORDER_NO); ? ? ? ? //符號(hào)位(1)bit、時(shí)間戳(2~42)bit | 序列號(hào)(43~59)bit | 機(jī)器碼(60~64)bit ? ? ? ? return currentTimeMillis | (orderNo << 5) | MACHINE_CODE; ? ? } }
SnowflakeIdGenerate
/** ?* 1bit ?? ??? ?+ 41bit ?? ??? ?+ 17bit ?? ??? ?+ 5bit ?* |?? ??? ??? ? ? ?|?? ??? ??? ??? ?|?? ??? ??? ??? ?| ?* |?? ??? ??? ??? ?|?? ??? ??? ??? ?|?? ??? ??? ??? ?| ?* 符合位 ? ? ?? ? ? ? ? ?時(shí)間戳(毫秒)?? ??? ? ? ? 序列號(hào)?? ??? ??? ? ? ? ?機(jī)器碼 ?* 第1bit固定是0 ?符號(hào)位不動(dòng) 。 ?* 第2bit到第42bit使用時(shí)間蹉,精確到毫秒 ?41bit。 使用年限是69年 ?* 第43bit到第59bit使用自增的序列號(hào) ? ? ? 17bit ?可用序列號(hào)最大131071個(gè),說(shuō)明一毫秒我們可以生成131071個(gè)不同的序列號(hào)。 ?* 第60bit到第64bit使用機(jī)器碼?? ?5bit ? 可以使系統(tǒng)可以分布式,最大分布式數(shù)量是32臺(tái)機(jī)子。 ?* ?*/ public class SnowflakeIdGenerate extends AbstractIdGenerate<Long> { ? ? public SnowflakeIdGenerate(final long machineCode) { ? ? ? ? super(machineCode); ? ? } ? ? @Override ? ? public Long generate() { ? ? ? ? return super.generateLong(); ? ? } }
自動(dòng)配置Bean
可以通過(guò)配置bean添加到容器,注入使用
/** ? * id生成 機(jī)器碼, 單機(jī)配置1即可。 集群部署,每個(gè)實(shí)例自增1即可。 ? * ? * @param machineCode ? * @return ? */ ?@Bean("snowflakeIdGenerate") ?public IdGenerate getIdGenerate(@Value("${id-generator.machine-code:1}") Long machineCode) { ? ? ?return new SnowflakeIdGenerate(machineCode); ?}
到此這篇關(guān)于java實(shí)現(xiàn)雪花算法ID生成器工具類(lèi)的文章就介紹到這了,更多相關(guān)java雪花算法ID生成工具類(lèi)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot http請(qǐng)求注解@RestController原理解析
這篇文章主要介紹了SpringBoot http請(qǐng)求注解@RestController原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01Java判斷中英文符號(hào)、標(biāo)點(diǎn)的實(shí)現(xiàn)
本篇文章主要介紹了Java判斷中英文符號(hào)、標(biāo)點(diǎn)的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10Maven的porfile與SpringBoot的profile結(jié)合使用案例詳解
這篇文章主要介紹了Maven的porfile與SpringBoot的profile結(jié)合使用,通過(guò)maven的profile功能,在打包的時(shí)候,通過(guò)-P指定maven激活某個(gè)pofile,這個(gè)profile里面配置了一個(gè)參數(shù)activatedProperties,不同的profile里面的這個(gè)參數(shù)的值不同,需要的朋友可以參考下吧2021-12-12SpringBoot利用dag加速Spring beans初始化的方法示例
本文介紹了利用DAG加速SpringBoot中Spring beans初始化,先解釋了DAG 概念及特性,包括節(jié)點(diǎn)入度出度、拓?fù)渑判虻?接著闡述加速Spring Bean初始化的實(shí)現(xiàn)思路,如識(shí)別依賴(lài)關(guān)系構(gòu)建DAG、拓?fù)渑判颉⒉⑿谐跏蓟疊ean及與Spring集成,還展示了相關(guān)代碼工程、測(cè)試結(jié)果及引用2024-12-12