分布式uuid生成器- snowflake java 版

package tools;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * User: FR
 * Time: 12/22/14 5:53 PM
 * 测试每秒270w的id生成能力
 */
public class UUID {

    private Long HORIZON_MILLI=1419242747142L;
    private final static Integer SEQUENCE_BITS=12;
    private final static Integer WORK_ID_BITS=5;
    private final static Integer DATA_CENTER_BITS=5;
    private final static Integer MILLI_SECOND_BITS=41;
    private final static Integer MAX_SEQUENCE=-1 ^ (-1<<SEQUENCE_BITS);
    private final static Integer MAX_WORK_ID=-1 ^ (-1<<WORK_ID_BITS);
    private final static Integer MAX_DATA_CENTER_ID=-1 ^ (-1 << DATA_CENTER_BITS);
    private final static Long MAX_MILLISECONDS = -1L ^ (-1L << MILLI_SECOND_BITS);

    private final static Integer MILLI_SHIFT= DATA_CENTER_BITS + WORK_ID_BITS + SEQUENCE_BITS;
    private final static Integer DATA_CENTER_SHIFT= WORK_ID_BITS + SEQUENCE_BITS;
    private final static Integer WORK_ID_SHIFT= SEQUENCE_BITS;


    private Integer work_id=1;
    private Integer data_center_id=1;


    private long sequence = 0;
    private long lastTimestamp=0;

    public UUID(Integer workId, Integer dataCenterId) {
        if((workId & MAX_WORK_ID) == 0){
            throw new RuntimeException("work id is too large");
        }
        if((dataCenterId & MAX_DATA_CENTER_ID) == 0){
            throw new RuntimeException("data center id is too large");
        }
        this.work_id = workId;
        this.data_center_id = dataCenterId;
    }

    public synchronized long nextId(){
        long milliseconds = System.currentTimeMillis();
        if(this.lastTimestamp == milliseconds){
            this.sequence = (this.sequence+1) & MAX_SEQUENCE;
            if(this.sequence == 0){
                milliseconds = tilNextMillis(this.lastTimestamp);
            }
        }else if(milliseconds < this.lastTimestamp){
            throw new RuntimeException("clock wrong");
        }else {
            this.sequence = 0;
        }
        this.lastTimestamp = milliseconds;
        if(((milliseconds-HORIZON_MILLI) & MAX_MILLISECONDS) == 0){
            throw new RuntimeException("time is too large");
        }
        long nextId = ((milliseconds-HORIZON_MILLI)<<MILLI_SHIFT)+(this.data_center_id<<DATA_CENTER_SHIFT)+(this.work_id<<WORK_ID_SHIFT)+this.sequence;
        return nextId;
    }

    private long tilNextMillis(final long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }

    public static void main(String[] args) throws InterruptedException {
        final AtomicInteger counter = new AtomicInteger(0);
        final ConcurrentHashMap set = new ConcurrentHashMap();
        final UUID uuid = new UUID(31, 1);
        final CountDownLatch countDownLatch = new CountDownLatch(100);
        final long start = System.currentTimeMillis();
        for (int i=0; i<100; i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while ((System.currentTimeMillis() - start)<6000){
                        long id = uuid.nextId();
                        set.put(id, "");
                        counter.incrementAndGet();
                    }
                    countDownLatch.countDown();
                }
            }).start();
        }
        countDownLatch.await();
        long end = System.currentTimeMillis();
        System.out.println("use time " + (end - start));
        System.out.println(counter.get() + "");
        System.out.println(set.keySet().size());
    }

    public static void main1(String[] args){
        System.out.println(Long.toBinaryString(MAX_MILLISECONDS));
        long start = System.currentTimeMillis();
        UUID uuid = new UUID(31, 1);
        Set<Long> set = new HashSet<Long>();
        while ((System.currentTimeMillis() - start)<6000){
            long id = uuid.nextId();
            set.add(id);
        }
        System.out.println(set.size());
    }
}

猜你喜欢

转载自blue2048.iteye.com/blog/2169442