【Vesta發(fā)號器源碼】AtomicIdPopulator

Vesta發(fā)號器源碼解析——AtomicIdPopulator

這個類是核心的,用于生成ID的關鍵類之一,是一個實現(xiàn)了IdPopulator, ResetPopulator接口的ID生成類

內(nèi)部類Variant

這個類用于持有在一個生成周期內(nèi)的上一次時間戳以及當前的序列值


    class Variant {

        private long sequence = 0;
        private long lastTimestamp = -1;

    }
    //利用AtomicReference引用Variant進行操作保證原子性
    private AtomicReference<Variant> variant = new AtomicReference<Variant>(new Variant());

構造方法

    public AtomicIdPopulator() {
        super();
    }

populateId方法

核心方法,生成Id中的主要動態(tài)部分,時間和序列號

    public void populateId(Timer timer, Id id, IdMeta idMeta) {
        //新老兩個準備好
        Variant varOld, varNew;
        //臨時性的變量存儲時間戳和序列值
        long timestamp, sequence;
        //不斷嘗試  直到出現(xiàn)退出條件break
        while (true) {

            //先存好舊的variant
            varOld = variant.get();

            // 生成當前的variant
            //首先是當前周期的時間戳,區(qū)分毫秒級和秒級,在timer中實現(xiàn)
            timestamp = timer.genTime();
            //校驗時間戳,具體實現(xiàn)在timer中,用于確保使用時間沒有超限制
            timer.validateTimestamp(varOld.lastTimestamp, timestamp);
            //記錄原始的sequence
            sequence = varOld.sequence;
            
            //判斷是否位于同一個周期內(nèi),是的話累加sequ否則重置sequence
            if (timestamp == varOld.lastTimestamp) {
                //sequence累加
                sequence++;
                //確保sequence沒有超過限制,超限會導致sequence變成0
                sequence &= idMeta.getSeqBitsMask();
                if (sequence == 0) {
                    //超過限制了,等待下一個周期來臨,直到來臨后返回新的時間戳
                    timestamp = timer.tillNextTimeUnit(varOld.lastTimestamp);
                }
            } else {
                //不在同一個周期,重置sequence
                sequence = 0;
            }

            // 利用原子操作類的CAS特性更新variant
            varNew = new Variant();
            varNew.sequence = sequence;
            varNew.lastTimestamp = timestamp;

            if (variant.compareAndSet(varOld, varNew)) {
                //更新成功后,組裝傳進來的id
                id.setSeq(sequence);
                id.setTime(timestamp);
                //ID生成成功,退出循環(huán)
                break;
            }

        }
    }

Reset方法

用于在下個時間周期來臨的時候重置當先的variant,從而能夠為后續(xù)的周期服務

    public void reset() {
        variant = new AtomicReference<Variant>(new Variant());
    }
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容