IdGenerator 唯一Id生成器

public class IdGenerator {

    private final static long beginTs = 1483200000000L;

    private long lastTs = 0L;

    private long processId;
    private int processIdBits = 10;

    private long sequence = 0L;
    private int sequenceBits = 12;

    public IdGenerator() {
    }

    public IdGenerator(long processId) {
        if (processId > ((1 << processIdBits) - 1)) {
            throw new RuntimeException("进程ID超出范围,设置位数" + processIdBits + ",最大" + ((1 << processIdBits) - 1));
        }
        this.processId = processId;
    }

    protected long timeGen() {
        return System.currentTimeMillis();
    }

    public synchronized long nextId() {
        long ts = timeGen();
        // 刚刚生成的时间戳比上次的时间戳还小,出错
        if (ts < lastTs) {
            throw new RuntimeException("时间戳顺序错误");
        }
        // 刚刚生成的时间戳跟上次的时间戳一样,则需要生成一个sequence序列号
        if (ts == lastTs) {
            // sequence循环自增
            sequence = (sequence + 1) & ((1 << sequenceBits) - 1);
            // 如果sequence=0则需要重新生成时间戳
            if (sequence == 0) {
                // 且必须保证时间戳序列往后
                ts = nextTs(lastTs);
            }
            // 如果ts>lastTs,时间戳序列已经不同了,此时可以不必生成sequence了,直接取0
        } else {
            sequence = 0L;
        }
        // 更新lastTs时间戳
        lastTs = ts;
        return ((ts - beginTs) << (processIdBits + sequenceBits)) | (processId << sequenceBits) | sequence;
    }

    public Long nextShortId() {
        Long shortId = System.currentTimeMillis() / 100 % 1000000000;
        if (shortId < 100000000) {
            shortId += 100000000;
        }
        return shortId;
    }

    protected long nextTs(long lastTs) {
        long ts = timeGen();
        while (ts <= lastTs) {
            ts = timeGen();
        }
        return ts;
    }

}

试一下这个算法的效率:

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        IdGenerator ig = new IdGenerator(1023);
        Long start = System.currentTimeMillis();
        Set set = new HashSet();
        for (int i = 0; i < 100000; i++) {
            set.add(ig.nextId());
        }
        System.out.println(set.size());
        System.out.println(System.currentTimeMillis() - start);
    }

结果:

set.size(): 100000
time:115

你可能感兴趣的:(Java基础)