工具类:
-
package com.ihrm.common.utils;
-
-
import java.lang.management.ManagementFactory;
-
import java.net.InetAddress;
-
import java.net.NetworkInterface;
-
-
//雪花算法代码实现
-
public
class IdWorker {
-
// 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
-
private
final
static
long twepoch =
1288834974657L;
-
// 机器标识位数
-
private
final
static
long workerIdBits =
5L;
-
// 数据中心标识位数
-
private
final
static
long datacenterIdBits =
5L;
-
// 机器ID最大值
-
private
final
static
long maxWorkerId = -
1L ^ (-
1L << workerIdBits);
-
// 数据中心ID最大值
-
private
final
static
long maxDatacenterId = -
1L ^ (-
1L << datacenterIdBits);
-
// 毫秒内自增位
-
private
final
static
long sequenceBits =
12L;
-
// 机器ID偏左移12位
-
private
final
static
long workerIdShift = sequenceBits;
-
// 数据中心ID左移17位
-
private
final
static
long datacenterIdShift = sequenceBits + workerIdBits;
-
// 时间毫秒左移22位
-
private
final
static
long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
-
-
private
final
static
long sequenceMask = -
1L ^ (-
1L << sequenceBits);
-
/* 上次生产id时间戳 */
-
private
static
long lastTimestamp = -
1L;
-
// 0,并发控制
-
private
long sequence =
0L;
-
-
private
final
long workerId;
-
// 数据标识id部分
-
private
final
long datacenterId;
-
-
public IdWorker(){
-
this.datacenterId = getDatacenterId(maxDatacenterId);
-
this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
-
}
-
/**
-
* @param workerId
-
* 工作机器ID
-
* @param datacenterId
-
* 序列号
-
*/
-
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;
-
}
-
/**
-
* 获取下一个ID
-
*
-
* @return
-
*/
-
public 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) {
-
// 当前毫秒内,则+1
-
sequence = (sequence +
1) & sequenceMask;
-
if (sequence ==
0) {
-
// 当前毫秒内计数满了,则等待下一秒
-
timestamp = tilNextMillis(lastTimestamp);
-
}
-
}
else {
-
sequence =
0L;
-
}
-
lastTimestamp = timestamp;
-
// ID偏移组合生成最终的ID,并返回ID
-
long nextId = ((timestamp - twepoch) << timestampLeftShift)
-
| (datacenterId << datacenterIdShift)
-
| (workerId << workerIdShift) | sequence;
-
-
return nextId;
-
}
-
-
private long tilNextMillis(final long lastTimestamp) {
-
long timestamp =
this.timeGen();
-
while (timestamp <= lastTimestamp) {
-
timestamp =
this.timeGen();
-
}
-
return timestamp;
-
}
-
-
private long timeGen() {
-
return System.currentTimeMillis();
-
}
-
-
/**
-
* <p>
-
* 获取 maxWorkerId
-
* </p>
-
*/
-
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
-
StringBuffer mpid =
new StringBuffer();
-
mpid.append(datacenterId);
-
String name = ManagementFactory.getRuntimeMXBean().getName();
-
if (!name.isEmpty()) {
-
/*
-
* GET jvmPid
-
*/
-
mpid.append(name.split(
"@")[
0]);
-
}
-
/*
-
* MAC + PID 的 hashcode 获取16个低位
-
*/
-
return (mpid.toString().hashCode() &
0xffff) % (maxWorkerId +
1);
-
}
-
-
/**
-
* <p>
-
* 数据标识id部分
-
* </p>
-
*/
-
protected static long getDatacenterId(long maxDatacenterId) {
-
long id =
0L;
-
try {
-
InetAddress ip = InetAddress.getLocalHost();
-
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
-
if (network ==
null) {
-
id =
1L;
-
}
else {
-
byte[] mac = network.getHardwareAddress();
-
id = ((
0x000000FF & (
long) mac[mac.length -
1])
-
| (
0x0000FF00 & (((
long) mac[mac.length -
2]) <<
8))) >>
6;
-
id = id % (maxDatacenterId +
1);
-
}
-
}
catch (Exception e) {
-
System.out.println(
" getDatacenterId: " + e.getMessage());
-
}
-
return id;
-
}
-
}
使用:
-
IdWorker idWorker =
new IdWorker();
-
-
long id = idWorker.nextId();