您的位置:首页 > 科技 > 能源 > 【雪花算法】

【雪花算法】

2024/9/30 6:31:37 来源:https://blog.csdn.net/qq_43676797/article/details/139899606  浏览:    关键词:【雪花算法】

雪花算法

package com.shaoby.common.utils;import com.shaoby.common.enums.ExceptionEnum;
import com.shaoby.common.exception.ApiException;import java.time.*;
import java.util.*;
import java.util.concurrent.CountDownLatch;/*** 雪花算法生产64位全局唯一ID* 1位符号位* 41位存储时间戳* 5位存储机器ID* 5位存储服务ID* 12位自增序列号* @Author Cookie* @Date 2024/6/23 1:12*/
public class SnowFlakeUtils {//机器ID,暂时写死private long workerid = 0;//服务ID,暂时写死private long serviceid = 0;//2024-01-01 00:00:00时间戳private final long basicTime = 1704038400000L;//机器ID所占的位数private final long workerIdBits = 5L;//服务ID所占位数private final long serviceBitId = 5L;//机器ID最大值,用于校验机器IDprivate final long maxWorkIdBit = -1 ^ (-1 << workerIdBits);//服务ID最大值,用于校验服务器IDprivate final long maxServiceIdBit = -1 ^ (-1 << serviceBitId);//序列在ID中占的位数private final long sequenceBits = 12L;//机器ID左移12位;private final long workerIdShift = sequenceBits;//服务ID左移17位private final long serviceIdShift = sequenceBits + sequenceBits;//时间戳左移22位private final long timeShift = sequenceBits + sequenceBits + workerIdBits;//毫秒内最大序列号private final long maxSequence = (-1L) ^(-1 << sequenceBits);//毫秒内序列private long sequence = 0L;//上次生成序号时间戳private long lastTimestamp = 0L;public synchronized long getNextId(){//当前时间戳long timestamp = timeGen();//时间回溯抛异常if(timestamp < lastTimestamp){throw new ApiException(ExceptionEnum.TIME_BACK_ERROR);}//如果是毫秒内生成sequence+1if(timestamp == lastTimestamp){/*** 当毫秒内生成的序列号没有超过最大值时候,直接加一,* 如果超过了最大值会溢出,十二位不够存储,比如 1111 1111 1111 1111再加一回多一位变成 1 0000 0000 0000,* 这里这样处理:去 & 上一个最大值,* 如果超过了最大值,即 1 0000 0000 0000 &  1111 1111 1111 变成 0000 0000 0000* 如果没有超过最大值,如 1111 0000 0000 & 1111 1111 1111 还是 1111 0000 0000,不变*/sequence = (sequence+1) & maxSequence;/** 如果为0表示超过了最大值,则放到下一毫秒生成*/if(sequence == 0L){timestamp = nextTimeGen(timestamp);}}else {sequence = 0;}lastTimestamp = timestamp;return ((timestamp-basicTime) << timeShift) | (workerid << workerIdShift) | (serviceid << serviceIdShift) | sequence;}/** 获取当前时间戳*/private long timeGen() {return System.currentTimeMillis();}/** 获取下一毫秒时间戳*/private long nextTimeGen(long time){//拿到当前时间戳long timeStamp = timeGen();//如过还在当前毫秒内,重新获取当前时间,只到拿到非当前毫秒内时间戳while (time <= timeStamp){timeStamp = timeGen();}return timeStamp;}public static void main(String[] args) throws InterruptedException {SnowFlakeUtils snowFlakeUtils = new SnowFlakeUtils();Set<Object> set = Collections.synchronizedSet(new LinkedHashSet<>());int threadCount = 500;CountDownLatch latch = new CountDownLatch(threadCount);for (int i = 0; i < threadCount; i++) {new Thread(() -> {long nextId = snowFlakeUtils.getNextId();System.out.println(Thread.currentThread().getName() +"--->"+ nextId);set.add(nextId);latch.countDown();}).start();}latch.await();System.out.println(set.size());}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com