1. 程式人生 > >snowflake演算法生成唯一ID

snowflake演算法生成唯一ID

/**
 * snowflake演算法生成唯一ID
 */
public class IdWorker {
	
	private static final long twepoch = 1288834974657L;
	private static final long workerIdBits = 5L;
	private static final long datacenterIdBits = 5L;
	//private static final long maxWorkerId = -1L ^ (-1L << workerIdBits);
	//private static final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
	private static final long sequenceBits = 12L;
	private static final long workerIdShift = sequenceBits;
	private static final long datacenterIdShift = sequenceBits + workerIdBits;
	private static final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
	private static final long sequenceMask = -1L ^ (-1L << sequenceBits);

	private static final long workerId = 18;
	private static final long datacenterId = 01;
	private static long sequence = 0L;
	private static long lastTimestamp = -1L;
	
	/**
	 * @param workerId : 機器ID 0--31
	 * @param datacenterId : 業務ID  0--31
	
	public IdWorker(long workerId, long datacenterId) {
		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;
	} */

	public static synchronized long nextId() {
		long timestamp = timeGen();
		if (timestamp < lastTimestamp) {
			throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
		}
		if (lastTimestamp == timestamp) {
			sequence = (sequence + 1) & sequenceMask;
			if (sequence == 0) {
				timestamp = tilNextMillis(lastTimestamp);
			}
		} else {
			sequence = 0L;
		}
		lastTimestamp = timestamp;
		return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
	}
	
	protected static long tilNextMillis(long lastTimestamp) {
		long timestamp = timeGen();
		while (timestamp <= lastTimestamp) {
			timestamp = timeGen();
		}
		return timestamp;
	}
	
	protected static long timeGen() {
		return System.currentTimeMillis();
	}
	
	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		for (int i = 0; i < 1000000; i++) {
			String.valueOf(IdWorker.nextId());
		}
		System.out.println(String.valueOf(IdWorker.nextId()));
		System.out.println(String.valueOf(IdWorker.nextId()));
		System.out.println(String.valueOf(IdWorker.nextId()));
		System.out.println(String.valueOf(IdWorker.nextId()));
		System.out.println("生成100萬個訂單耗時:" + (System.currentTimeMillis()-start) + "毫秒");
	}

}