package org.voovan.tools;

import java.security.SecureRandom;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 高速ID生成器
 * 采用 snowflake 算法快速生成 ID
 *
 * @author: helyho
 * Voovan Framework.
 * WebSite: https://github.com/helyho/Voovan
 * Licence: Apache v2 License
 */
public class UniqueId {
    private static final int SEQ_DEFAULT = 0;
    private static final int RADIX = 62;
    private static final int sequenceLeft = 12;
    private static final int signIdLeft = 10;
    private static final int maxsignId = 1 << signIdLeft;

    private volatile AtomicInteger orderedIdSequence = new AtomicInteger(SEQ_DEFAULT);
    private Long lastTime = 0L;
    private int workId = 0;

    /**
     * 构造函数
     */
    public UniqueId() {
        int workId = (new SecureRandom()).nextInt(maxsignId);
        if(workId > maxsignId || workId < 0){
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxsignId));
        }
        workId = 0;
    }

    /**
     *  构造函数
     * @param signId 标识 ID
     */
    public UniqueId(int signId) {
        if(workId > maxsignId || signId < 0){
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxsignId));
        }
        workId = signId;
    }

    /**
     * 获取下一个 id
     * @return 返回 id
     */
    public long nextInt(){
        return generateId();
    }

    /**
     * 获取下一个 id
     * @return 返回 id
     */
    public String nextString(){
        return TString.radixConvert(generateId(), RADIX);
    }

    /**
     * 生成带顺序的 ID 序列
     * @return ID字符串
     */
    public synchronized long generateId(){
        long currentTime = System.currentTimeMillis();

        if(lastTime < currentTime){
            orderedIdSequence.set(SEQ_DEFAULT);
        }else if(lastTime > currentTime){
            throw new RuntimeException("Clock moved backwards.");
        }

        long resultId = (currentTime << (sequenceLeft+signIdLeft) ) | (workId << signIdLeft) | orderedIdSequence.getAndAdd(1);

        lastTime = currentTime;
        return resultId;
    }
}

@@ -409,28 +409,29 @@
 nal int 
-sequenceLeft
+SEQUENCE_LEFT
  = 12;%0A 
@@ -458,26 +458,27 @@
 nal int 
-signIdLeft
+SIGNID_LEFT
  = 10;%0A 
@@ -509,35 +509,37 @@
 int 
-maxsignId = 1 %3C%3C signIdLeft
+MAX_SIGNID = 1 %3C%3C SIGNID_LEFT
 ;%0A%0A 
@@ -787,25 +787,26 @@
 nextInt(
-maxsignId
+MAX_SIGNID
 );%0A     
@@ -816,33 +816,34 @@
 if(workId %3E 
-maxsignId
+MAX_SIGNID
  %7C%7C workId %3C
@@ -957,33 +957,34 @@
 ss than 0%22, 
-maxsignId
+MAX_SIGNID
 ));%0A        
@@ -1117,26 +1117,27 @@
  if(
-workId %3E maxsignId
+signId %3E MAX_SIGNID
  %7C%7C 
@@ -1267,17 +1267,18 @@
 0%22, 
-maxsignId
+MAX_SIGNID
 ));%0A
@@ -1940,24 +1940,106 @@
 %0A        %7D%0A%0A
+        if(orderedIdSequence.get() %3E 2096)%7B%0A            TEnv.sleep(1);%0A        %7D%0A%0A
         long
@@ -2071,31 +2071,35 @@
 %3C%3C (
-sequenceLeft+signIdLeft
+SEQUENCE_LEFT + SIGNID_LEFT
 ) ) 
@@ -2115,18 +2115,21 @@
  %3C%3C 
-signIdLeft
+SEQUENCE_LEFT
 ) %7C 

修复 Unique 可能重复的问题