shikeying
2024-01-11 3b67e947e36133e2a40eb2737b15ea375e157ea0
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
package com.walker.infrastructure.utils;
 
import com.walker.infrastructure.ServerId;
 
import java.util.UUID;
 
public abstract class NumberGenerator {
 
    public static final long[] DIGIT_SIZE_TABLE = {9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999
            , 9999999999L, 99999999999L, 999999999999L, 9999999999999L, 99999999999999L, 999999999999999L, 9999999999999999L
            , 99999999999999999L, 999999999999999999L};
 
    public static final int NANO_SIZE = 16;
 
    public static final long getLongSequenceNumberNano(){
//        LocalDateTime localDateTime = LocalDateTime.now();
//        System.out.println("getNano = " + localDateTime.getNano());
//        Clock clock = Clock.systemDefaultZone();
//        Instant instant = Instant.now();   // or Instant.now();
//        long seconds = instant.getEpochSecond();
//        long nano = instant.getNano();
//        return (seconds * 1000000000 + nano);
        long nano = System.nanoTime();
        if(nano < 0){
            nano = Math.abs(nano);
        }
        long id = System.currentTimeMillis() + nano;
        int idSize = getDigitBitSize(id);
        if(idSize > NANO_SIZE){
            // 超过16位,必须重新生成
            id = System.currentTimeMillis() * 1000 + Long.parseLong(StringUtils.generateRandomNumber(3));
        }
        return id;
//        return System.currentTimeMillis() + nano;
    }
 
    private static final int getDigitBitSize(long value){
        for (int i = 0;; i++)
            if (value <= DIGIT_SIZE_TABLE[i])
                return i + 1;
    }
 
    /**
     * 得到顺序数,此方法根据系统当前时间生成毫秒数。</p>
     * 对于数据量不大(通常每秒钟小于1000)的访问可以使用。</br>
     * 如果更大,可以使用<code>getSequenceNumber()</code>方法。
     * @return
     */
    public static final long getSequenceNumber(){
        return System.currentTimeMillis();
    }
 
    /**
     * 返回15位的数值,这是根据系统纳秒数生成的。
     * @return
     * @date 2015-07-12
     * @date 2023-06-29 重写方法,是用毫秒与纳秒结合方式生成序列,因为纯纳秒方法与虚拟机启动有关,在虚拟机不停重启时仍然会重复
     */
    public static final long getLongSequenceNumber(){
//        long v = System.nanoTime();
//        if(v < 0){
//            return Math.abs(v);
//        }
//        return v;
        return getLongSequenceNumberNano();
    }
 
    /**
     * 返回纳秒值长整形数字,转为字符串。
     * @return
     * @date 2022-08-12
     * @date 2023-10-07 生成支持集群的字符串ID,通过本机配置的主机ID(serverId)
     * @date 2023-10-13 由于id在文件命名中不能使用冒号,所以变更为下划线。
     */
    public static final String getLongSequenceId(){
//        return String.valueOf(getLongSequenceNumber());
        return new StringBuilder(ServerId.getId())
                .append(StringUtils.STRING_UNDERLINE).append(NumberGenerator.getLongSequenceNumber())
                .append(StringUtils.STRING_UNDERLINE).append(StringUtils.generateRandomNumber(5)).toString();
    }
 
    /**
     * 产生32位随机字符串
     * @return
     */
    public static String generatorHexUUID(){
        return UUID.randomUUID().toString();
    }
 
    /**
     * @param args
     */
    public static void main(String[] args) {
//        for(int i=0; i<3; i++){
//            long startTime = System.nanoTime();
//            long result = getSequenceNumber();
//            System.out.println(result);
//            System.out.println("times: " + (System.nanoTime()-startTime));
//        }
//        System.out.println("long sequence: " + getLongSequenceNumber());
//
//        long value = getSequenceNumber();
//        Date date = new Date(value);
//        System.out.println(date);
 
//        List<Integer> list = new ArrayList<>();
        long startTime = 0;
        long nanoSecond = 0;
        for(int i=0; i<30; i++){
            startTime = System.nanoTime();
            nanoSecond = getLongSequenceNumberNano();
            System.out.println(nanoSecond + ", total time = " + (System.nanoTime() - startTime));
        }
 
        long mod = System.nanoTime() % 10;
        System.out.println(mod);
    }
 
}