数据库存储的是两个Long类型的复合主键。显示到页面的是一个27位的数字单号
1 package com.yunyihenkey.common.idworker; 2 3 /** 4 * 5 * @desc 6 * @author jon snow 7 * @version 1.0.0 8 */ 9 public class SuperSnowflakeIdWorker { 10 11 public static class NextId { 12 private Long id1; 13 private Long id2; 14 15 public NextId(Long id1, Long id2) { 16 this.id1 = id1; 17 this.id2 = id2; 18 } 19 20 public Long getId1() { 21 return id1; 22 } 23 24 public void setId1(Long id1) { 25 this.id1 = id1; 26 } 27 28 public Long getId2() { 29 return id2; 30 } 31 32 public void setId2(Long id2) { 33 this.id2 = id2; 34 } 35 36 } 37 38 /** 开始时间截(秒) */ 39 public static final long birth = 1498939440L; 40 41 /** 机器id所占的位数 */ 42 public static final long workerIdBits = 20L; 43 44 /** 序列在id中占的位数 */ 45 public static final long sequenceBits = 43L; 46 47 /** 支持的最大机器id (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */ 48 public static final long maxWorkerId = -1L ^ (-1L << workerIdBits); 49 50 /** 序列最大值 */ 51 public static final long sequenceMask = -1L ^ (-1L << sequenceBits); 52 53 /** 工作机器ID(0~1048575 ) */ 54 private long workerId; 55 56 /** 秒内序列(0~8796093022207) */ 57 private long sequence = 0L; 58 59 /** 上次生成ID的时间截 */ 60 private long lastTimestamp = -1L; 61 62 public SuperSnowflakeIdWorker(long workerId) { 63 if (workerId > maxWorkerId || workerId < 0) { 64 throw new IllegalArgumentException( 65 String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); 66 } 67 this.workerId = workerId; 68 } 69 70 public synchronized NextId nextId() { 71 long timestamp = timeGen(); 72 73 // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 74 if (timestamp < lastTimestamp) { 75 throw new RuntimeException(String.format( 76 "Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); 77 } 78 79 // 如果是同一时间生成的,则进行秒内序列 80 if (lastTimestamp == timestamp) { 81 sequence = (sequence + 1) & sequenceMask; 82 // 秒内序列溢出 83 if (sequence == 0) { 84 // 阻塞到下一个秒,获得新的时间戳 85 timestamp = tilNextMillis(lastTimestamp); 86 } 87 } 88 // 时间戳改变,秒内序列重置 89 else { 90 sequence = 0L; 91 } 92 93 // 上次生成ID的时间截 94 lastTimestamp = timestamp; 95 96 // 移位并通过或运算拼到一起组成64位的ID 97 // long l = (workerId << sequenceBits) | sequence; 98 99 // System.out.println(Long.toBinaryString(workerId) + ":+:" + 100 // Long.toBinaryString(sequence)); 101 // String binaryString = Long.toBinaryString(l); 102 // System.out.println("生成:" + zero.substring(0, 63 - binaryString.length()) + 103 // binaryString); 104 // System.out.println("生成数字:" + l + ":原始数字:" 105 // + Long.valueOf(Long.toBinaryString(workerId) + Long.toBinaryString(sequence), 106 // 2) + "end"); 107 108 // return new long[] { timestamp - birth, (workerId << sequenceBits) | sequence 109 // }; 110 return new NextId(timestamp - birth, (workerId << sequenceBits) | sequence); 111 } 112 113 /** 114 * 阻塞到下一个秒,直到获得新的时间戳 115 * 116 * @param lastTimestamp 117 * 上次生成ID的时间截 118 * @return 当前时间戳 119 */ 120 protected long tilNextMillis(long lastTimestamp) { 121 long timestamp = timeGen(); 122 while (timestamp <= lastTimestamp) { 123 timestamp = timeGen(); 124 } 125 return timestamp; 126 } 127 128 private long timeGen() { 129 return System.currentTimeMillis() / 1000; 130 } 131 132 /** 测试生成id */ 133 public static void main(String[] args) { 134 135 SuperSnowflakeIdWorker idWorker = new SuperSnowflakeIdWorker(666); 136 long currentTimeMillis = System.currentTimeMillis(); 137 int times = 100000000; 138 for (int i = 0; i < times; i++) { 139 140 // 获取一个复合主键id 141 // NextId nextId = idWorker.nextId(); 142 idWorker.nextId(); 143 144 // System.out.println(Long.toBinaryString(id)); 145 146 // System.out.println("--------------------------------"); 147 // String zero = 148 // "000000000000000000000000000000000000000000000000000000000000000";// 63个0 149 // String binaryString = Long.toBinaryString(nextId.getId2()); 150 // BigInteger bigInteger = new BigInteger( 151 // Long.toBinaryString(nextId.getId1()) + zero.substring(0, 63 - 152 // binaryString.length()) + binaryString, 153 // 2); 154 // String string = bigInteger.toString(); 155 // System.out.println("数据库存储:id1=" + nextId.getId1() + "::id2=" + 156 // nextId.getId2() + "::::页面显示订单号:" + string); 157 // String string2 = bigInteger.toString(2); 158 // System.out.println("id的比特字节::" + string2); 159 // 160 // int endIndex = string2.length() - 63; 161 // System.out 162 // .println("前端传过来的订单号:" + string + "" + " 解析-->id1=" + 163 // Long.valueOf(string2.substring(0, endIndex), 2) 164 // + "::id2=" + Long.valueOf(string2.substring(endIndex), 2)); 165 } 166 167 long cost = System.currentTimeMillis() - currentTimeMillis; 168 long l = times / (cost == 0 ? 1 : cost) * 1000; 169 System.out.println(" 耗时(ms):" + cost + ",速度(万每秒):" + (l / 10000)); 170 171 } 172 173 // /** 测试是否重复 */ 174 // public static final ConcurrentHashMap<Object, Object> map = new 175 // ConcurrentHashMap<>(1000100); 176 /** 测试是否重复 */ 177 // public static void main666(String[] args) { 178 // // 9个线程 179 // for (int i = 0; i < 9; i++) { 180 // new Thread(new Runnable() { 181 // @Override 182 // public void run() { 183 // MySnow idWorker = new MySnow(Thread.currentThread().getId()); 184 // for (int j = 0; j < 1000000; j++) { 185 // NextId nextId = idWorker.nextId(); 186 // Object put = map.put(Long.toString(nextId.getId1()) + 187 // Long.toString(nextId.getId2()), 1); 188 // if (put != null) { 189 // System.out.println("id重复!!!"); 190 // } 191 // } 192 // System.out.println(Thread.currentThread().getId() + ",线程跑完"); 193 // } 194 // }).start(); 195 // 196 // } 197 // 198 // } 199 200 }