一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java收集的雪花算法代碼詳解

Java收集的雪花算法代碼詳解

2022-02-13 15:00java265 Java教程

這篇文章主要介紹了Java實現雪花算法的詳細代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

?
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package com.java265.other;
 
 
public class Test {
 
    // 因為二進制里第一個 bit 為如果是 1,那么都是負數,但是我們生成的 id 都是正數,所以第一個 bit 統一都是 0。
 
    // 機器ID 2進制5位 32位減掉1位 31個
    private long workerId;
    // 機房ID 2進制5位 32位減掉1位 31個
    private long datacenterId;
    // 代表一毫秒內生成的多個id的最新序號 12位 4096 -1 = 4095 個
    private long sequence;
    // 設置一個時間初始值 2^41 - 1 差不多可以用69年
    private long twepoch = 1585644268888L;
    // 5位的機器id
    private long workerIdBits = 5L;
    // 5位的機房id
    private long datacenterIdBits = 5L;
    // 每毫秒內產生的id數 2 的 12次方
    private long sequenceBits = 12L;
    // 這個是二進制運算,就是5 bit最多只能有31個數字,也就是說機器id最多只能是32以內
    private long maxWorkerId = -1L ^ (-1L << workerIdBits);
    // 這個是一個意思,就是5 bit最多只能有31個數字,機房id最多只能是32以內
    private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
 
    private long workerIdShift = sequenceBits;
    private long datacenterIdShift = sequenceBits + workerIdBits;
    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    private long sequenceMask = -1L ^ (-1L << sequenceBits);
    // 記錄產生時間毫秒數,判斷是否是同1毫秒
    private long lastTimestamp = -1L;
 
    public long getWorkerId() {
        return workerId;
    }
 
    public long getDatacenterId() {
        return datacenterId;
    }
 
    public long getTimestamp() {
        return System.currentTimeMillis();
    }
 
    public Test(long workerId, long datacenterId, long sequence) {
 
        // 檢查機房id和機器id是否超過31 不能小于0
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(
                    String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
 
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
 
            throw new IllegalArgumentException(
                    String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
        this.sequence = sequence;
    }
 
    // 這個是核心方法,通過調用nextId()方法,讓當前這臺機器上的snowflake算法程序生成一個全局唯一的id
    public synchronized long nextId() {
        // 這兒就是獲取當前時間戳,單位是毫秒
        long timestamp = timeGen();
        if (timestamp < lastTimestamp) {
 
            System.err.printf("clock is moving backwards. Rejecting requests until %d.", lastTimestamp);
            throw new RuntimeException(String.format(
                    "Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }
 
        // 下面是說假設在同一個毫秒內,又發送了一個請求生成一個id
        // 這個時候就得把seqence序號給遞增1,最多就是4096
        if (lastTimestamp == timestamp) {
 
            // 這個意思是說一個毫秒內最多只能有4096個數字,無論你傳遞多少進來,
            // 這個位運算保證始終就是在4096這個范圍內,避免你自己傳遞個sequence超過了4096這個范圍
            sequence = (sequence + 1) & sequenceMask;
            // 當某一毫秒的時間,產生的id數 超過4095,系統會進入等待,直到下一毫秒,系統繼續產生ID
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
 
        } else {
            sequence = 0;
        }
        // 這兒記錄一下最近一次生成id的時間戳,單位是毫秒
        lastTimestamp = timestamp;
        // 這兒就是最核心的二進制位運算操作,生成一個64bit的id
        // 先將當前時間戳左移,放到41 bit那兒;將機房id左移放到5 bit那兒;將機器id左移放到5 bit那兒;將序號放最后12 bit
        // 最后拼接起來成一個64 bit的二進制數字,轉換成10進制就是個long型
        return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift)
                | (workerId << workerIdShift) | sequence;
    }
 
    /**
     * 當某一毫秒的時間,產生的id數 超過4095,系統會進入等待,直到下一毫秒,系統繼續產生ID
     *
     * @param lastTimestamp
     * @return
     */
    private long tilNextMillis(long lastTimestamp) {
 
        long timestamp = timeGen();
 
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }
 
    // 獲取當前時間戳
    private long timeGen() {
        return System.currentTimeMillis();
    }
 
    /**
     * main 測試類
     *
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(1 & 4596);
        System.out.println(2 & 4596);
        System.out.println(6 & 4596);
        System.out.println(6 & 4596);
        System.out.println(6 & 4596);
        System.out.println(6 & 4596);
        Test test = new Test(1, 1, 1);
        for (int i = 0; i < 22; i++) {
            System.out.println(test.nextId());
        }
    }
}

總結

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!

原文鏈接:https://www.cnblogs.com/java265/p/15370568.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: japanese日本护士 | aa一级护士医生毛片 | 逼毛片 | 朝鲜女人性猛交 | 亚洲日本中文字幕天天更新 | 国产伦精品一区二区三区免费迷 | 国产欧美日韩综合 | 99精品全国免费7观看视频 | 精品国产美女福利在线 | 99久久精品国产综合一区 | 欧美专区亚洲 | 免费稚嫩福利 | h版在线观看 | 精品一久久香蕉国产线看观 | 52av我爱avhaose01| 古代翁熄系小说辣文 | 亚洲国产无线码在线观看 | 欧美折磨另类系列sm | 欧美美女被爆操 | 喜欢老头吃我奶躁我的动图 | 天天做日日做天天添天天欢公交车 | 99热在线只有精品 | 色婷婷综合缴情综六月 | 亚洲国产一区二区三区a毛片 | 成人免费视频在 | 秋霞理论一级在线观看手机版 | 毛片a区 | 美女撒尿部位无遮挡 | 操岳母娘| 日韩欧美一区二区在线 | 亚洲天堂影院在线观看 | 久久久无码精品无码国产人妻丝瓜 | 女人是男人的未来1分49分 | 色综合色狠狠天天综合色 | 女人把私密部位张开让男人桶 | 高h喷水荡肉爽文np肉色文 | 亚洲a视频在线 | 亚洲欧美精品天堂久久综合一区 | 国产麻豆麻豆 | 国产精品露脸国语对白手机视频 | 满溢游泳池免费土豪全集下拉版 |