| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- package com.ydtech.utils;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.HashSet;
- import java.util.Set;
- import java.util.concurrent.BrokenBarrierException;
- import java.util.concurrent.CyclicBarrier;
- import java.util.concurrent.TimeUnit;
- /**
- * Twitter_Snowflake<br>
- * SnowFlake改进符合业务的结构如下(每部分用-分开):<br>
- * bizCode(业务代码) + 201805051212(日期) + 4096(毫秒内随机数)<br>
- */
- /****
- * @ClassName: SnowflakeIdWorker
- * @Description:
- * @author ccc520
- * @date 2018年6月5日 上午8:44:27
- * @modificationHistory===============逻辑或功能性重大变更记录
- * @modify by user: (修改人)
- * @modify by reason: (修改原因)
- */
- public class SnowflakeIdVariant {
- // ==============================Fields===========================================
- /**
- * 序列在id中占的位数
- */
- private final long sequenceBits = 12L;
- /**
- * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
- */
- private final long sequenceMask = -1L ^ (-1L << sequenceBits);
- /**
- * 毫秒内序列(0~4095)
- */
- private long sequence = 0L;
- /**
- * 上次生成ID的时间截
- */
- private long lastTimestamp = -1L;
- private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>() {
- @Override
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat("yyyyMMddhhmmssSSS");
- }
- };
- //==============================Constructors=====================================
- /**
- * 构造函数
- */
- public SnowflakeIdVariant() {
- }
- // ==============================Methods==========================================
- /**
- * 获得下一个ID (该方法是线程安全的)
- *
- * @return SnowflakeId
- */
- public synchronized String nextId(String machineId, String bizCode) {
- long timestamp = timeGen();
- //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
- 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;
- }
- //上次生成ID的时间截
- lastTimestamp = timestamp;
- //移位并通过或运算拼到一起组成64位的ID
- // return bizCode + machineId + (threadLocal.get().format(new Date(timestamp))) + String.format("%05d",sequence);
- String precision = "5"; //几位序列号
- String format = "%0" + precision + "d";
- return bizCode + machineId + (threadLocal.get().format(new Date(timestamp))) + String.format(format, sequence);
- }
- /**
- * 阻塞到下一个毫秒,直到获得新的时间戳
- *
- * @param lastTimestamp 上次生成ID的时间截
- * @return 当前时间戳
- */
- protected long tilNextMillis(long lastTimestamp) {
- long timestamp = timeGen();
- while (timestamp <= lastTimestamp) {
- timestamp = timeGen();
- }
- return timestamp;
- }
- /**
- * 返回以毫秒为单位的当前时间
- *
- * @return 当前时间(毫秒)
- */
- protected long timeGen() {
- return System.currentTimeMillis();
- }
- //==============================Test=============================================
- /**
- * 测试
- */
- // public static void main(String[] args) throws InterruptedException {
- // System.out.println(SysConstants.MAC_ADDRESS);
- // String machineId = SysConstants.MAC_ADDRESS.replaceAll("-", "").substring(0,3);
- // SnowflakeIdVariant idWorker = new SnowflakeIdVariant();
- // long time1 = System.currentTimeMillis();
- // for (int i = 0; i < 100000; i++) {
- //// String id = idWorker.nextId("001","ORC");
- // String id = idWorker.nextId(machineId,"ORC");
- // //Thread.sleep(1);
- // System.out.println(id);
- // }
- // System.out.println(System.currentTimeMillis()-time1);
- // }
- // //////////// test ////////////
- public static void main(String[] args) throws Exception {
- final Set<String> set = new HashSet();
- SnowflakeIdVariant idWorker = new SnowflakeIdVariant();
- final CyclicBarrier cdl = new CyclicBarrier(100);
- for (int i = 0; i < 10000; i++) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- cdl.await();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (BrokenBarrierException e) {
- e.printStackTrace();
- }
- // id
- String id = idWorker.nextId("001", "ORC");
- if (set.contains(id)) {
- System.out.println(id + " exists");
- }
- set.add(id);
- System.out.println(id);
- // id2
- String id2 = idWorker.nextId("001", "ORC");
- if (set.contains(id2)) {
- System.out.println(id2 + " exists");
- }
- set.add(id2);
- System.out.println(id2);
- }
- }).start();
- }
- try {
- TimeUnit.SECONDS.sleep(5);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
|