All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.basics.util.IdGZQ Maven / Gradle / Ivy

package cn.basics.util;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName: IdGZQ
 * @Description: TODO(ID生成工具)
 * @author [email protected] (苟志强)
 * @date 2017-6-15 下午3:17:30
 * 高并发分布式系统中生成全局唯一Id
 * 优点:高性能,低延迟;独立的应用;按时间有序。
 * 缺点:需要独立的开发和部署
 */
public class IdGZQ {
	/*//循环生成ID 每次生成140万个ID 循环10次 查看效率
	public static void main(String[] args) throws Exception {
		long avg = 0;
		for (int k = 0; k < 10; k++) {
			List> partitions = new ArrayList>();
			final IdGZQ idGen = IdGZQ.get();
			for (int i = 0; i < 1400000; i++) {
				partitions.add(new Callable() {
					@Override
					public Long call() throws Exception {
						return idGen.nextId();
					}
				});
			}
			ExecutorService executorPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
			try {
				long s = System.currentTimeMillis();
				executorPool.invokeAll(partitions, 10000, TimeUnit.SECONDS);
				long s_avg = System.currentTimeMillis() - s;
				avg += s_avg;
				System.out.println("完成时间需要: " + s_avg / 1.0e3 + "秒");
				executorPool.shutdown();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		System.out.println("平均完成时间需要: " + avg / 10 / 1.0e3 + "秒");
	}*/
	
	public static void main(String[] args) {
		long id = IdGZQ.getId();
		System.out.println(id+":"+(id+"").length());
	}
	
	/**当前节点ID*/
	private long workerId;
	/**当前数据中心的身份ID*/
	private long datacenterId;
	/**序列号*/
	private long sequence = 0L;
	/**时间戳基值*/
	private long twepoch = 1504646413000L;//1481836813311L
	/**节点ID长度*/
	private long workerIdBits = 5L;
	/**数据中心ID长度*/
	private long datacenterIdBits = 5L;
	/**最大支持机器节点数0~31,一共32个*/
	private long maxWorkerId = -1L ^ (-1L << workerIdBits);
	/**最大支持数据中心节点数0~31,一共32个*/
	private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
	/**序列号12位*/
	private long sequenceBits = 12L;
	/**机器节点左移12位*/
	private long workerIdShift = sequenceBits;
	/**数据中心左移17位*/
	private long datacenterIdShift = sequenceBits + workerIdBits;
	/**时间毫秒数左移22位*/
	private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
	/**序列的面具4095*/
	private long sequenceMask = -1L ^ (-1L << sequenceBits);
	/**上一次获取ID的时间戳*/
	private long lastTimestamp = -1L;

	/**
	 * @ClassName: IdGZQHolder
	 * @Description: TODO(IdGZQ对象生成器)
	 * @author [email protected] (苟志强)
	 * @date 2017-6-15 下午3:54:26
	 */
	private static class IdGZQHolder {
		/**IdGZQ对象池 线程安全*/
		private static final ConcurrentHashMap IDGZQS_MAP = new ConcurrentHashMap();
		
		public static IdGZQ getGzq(long workerId, long datacenterId) {
			IdGZQ idGZQ = IDGZQS_MAP.get(workerId+","+datacenterId);
			if(idGZQ==null){
				idGZQ = new IdGZQ(workerId, datacenterId);
			}
			return idGZQ;
		}
	}
	/**
	 * @Title: get
	 * @Description: TODO(获取默认IdGZQ对象)
	 * @author [email protected] (苟志强)
	 * @date  2017-6-15 下午3:52:55
	 * @return
	 */
	public static IdGZQ get(){
		return IdGZQHolder.getGzq(1L,1L);
	}
	
	public static IdGZQ get(long workerId, long datacenterId){
		return IdGZQHolder.getGzq(workerId,datacenterId);
	}

	private IdGZQ() {
		this(1L, 1L);
	}
	/**
	 * 

Title: 构造方法

*

Description: 高并发分布式系统中生成全局唯一Id

* @author [email protected] (苟志强) * @param workerId 节点ID 可为0L * @param datacenterId 数据中心身份ID 可为0L */ private IdGZQ(long workerId, long datacenterId) { //验证节点ID是否符合规则 if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("节点ID不能大于%d或小于0", maxWorkerId)); } //验证数据中心的身份ID是否符合规则 if (datacenterId > maxDatacenterId || datacenterId < 0) { throw new IllegalArgumentException(String.format("数据中心的身份ID不能大于%d或少于0", maxDatacenterId)); } this.workerId = workerId; this.datacenterId = datacenterId; IdGZQHolder.IDGZQS_MAP.put(workerId+","+datacenterId, this); } /** * @Title: getId * @Description: TODO(以默认对象获取ID) * @author [email protected] (苟志强) * @date 2017-6-30 下午5:18:21 * @return */ public synchronized static long getId(){ return IdGZQ.get().aNextId(); } /** * @Title: aNextId * @Description: TODO(获取下一个ID<同步方法>,与nextId()方法一致!) * @author [email protected] (苟志强) * @date 2017-6-15 下午3:52:08 * @return */ public synchronized long aNextId() { return nextId(); } /** * @Title: nextId * @Description: TODO(获取下一个ID<同步方法>) * @author [email protected] (苟志强) * @date 2017-6-15 下午3:46:59 * @return */ public synchronized long nextId() { //获取当前毫秒数 long timestamp = getNowTime(); //如果服务器时间有问题(时钟后退) 报错。 if (timestamp < lastTimestamp) { throw new RuntimeException(String.format("当前时钟向后移动(当前时间戳小于上一次获取ID的时间戳)拒绝生成小于%d毫秒的id!", lastTimestamp - timestamp)); } //如果上次生成时间和当前时间相同,在同一毫秒内 if (lastTimestamp == timestamp) { //sequence自增,因为sequence只有12bit,所以和sequenceMask相与一下,去掉高位 sequence = (sequence + 1) & sequenceMask; //判断是否溢出,也就是每毫秒内超过4095,当为4096时,与sequenceMask相与,sequence就等于0 if (sequence == 0) { timestamp = tilNextMillis(lastTimestamp); //自旋等待到下一毫秒 } } else { sequence = 0L; //如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加 } lastTimestamp = timestamp; // 最后按照规则拼出ID。 // 000000000000000000000000000000000000000000 00000 00000 000000000000 // time datacenterId workerId sequence long nextId = ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift)| (workerId << workerIdShift) | sequence; // System.out.println("获取到的ID:" + nextId + ",生成信息:" +"时间戳“" + timestamp + "”,时间戳基值“" + twepoch + "”,时间毫秒数左移位数“" + timestampLeftShift + "”,数据中心身份ID“" + datacenterId + "”,数据中心左移位数“" + datacenterIdShift + "”,节点ID“" + workerId + "”,节点左移位数“" + workerIdShift + "”,序列号“" + sequence +"”"); return nextId; } /** * @Title: tilNextMillis * @Description: TODO(等待下一毫秒) * @author [email protected] (苟志强) * @date 2017-6-15 下午3:50:16 * @param lastTimestamp * @return */ protected long tilNextMillis(long lastTimestamp) { long timestamp = getNowTime(); while (timestamp <= lastTimestamp) { timestamp = getNowTime(); } return timestamp; } /** * @Title: getNowTime * @Description: TODO(获取当前时间戳) * @author [email protected] (苟志强) * @date 2017-6-15 下午3:50:47 * @return */ public long getNowTime() { return System.currentTimeMillis(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy