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

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美brazzers| 脱jk裙的美女露小内内无遮挡 | 千金肉奴隶在线观看 | 精品亚洲视频在线 | 夫妇交换小说全文阅读 | 久久国产综合精品欧美 | 紧身牛仔裤美女被啪啪久久网 | 大陆国产精品视频 | 人妖巨茎video| 日本高清视频网址 | 99久久国产综合精品女小说 | 91青青国产在线观看免费 | 精品视频手机在线观看免费 | 日日日操 | 国产欧美日韩成人 | 4p高h三男一女 | 九九在线精品视频 | 国产精品亚洲片在线观看麻豆 | 网红思瑞一区二区三区 | 成人亚洲欧美日韩中文字幕 | 扒开女人屁股眼看个够 | 特级老女人淫片高清视频 | 女人被爽到呻吟娇喘的视频动态图 | 久久爽狠狠添AV激情五月 | 波多野结衣女老师 | 热99精品只有里视频最新 | 91制片厂制作传媒网站 | 国产成人精品一区二三区2022 | 国产成人亚洲综合a∨婷婷 国产成人亚洲精品乱码在线观看 | 国产高清好大好夹受不了了 | 亚欧有色在线观看免费版高清 | 欧美贵妇vs高跟办公室 | 风间由美被义子中文字幕 | 国产精品每日在线观看男人的天堂 | 欧美高清国产 | 91小视频在线观看免费版高清 | 久久国产乱子伦精品免费不卡 | 精品国产乱码久久久人妻 | 国产亚洲欧美日韩俺去了 | 午夜精品久久久久 | 天天干狠狠操 |