雪花算法(ip+进程pid)
2018-09-26 本文已影响0人
白衣如相
import java.lang.management.ManagementFactory;
import java.math.BigInteger;
import java.util.concurrent.locks.ReentrantLock;
/**
* 产生唯一ID的snow flake
* 41(timestamp)+16(ip)+18(pid)+8(seq)
*
* @author changstone
*
*/
public class Snowflake {
/**
* 纪元开始,2018-01-01
*/
private static final long TH_EPOCH = 1514736000000L;
private int timestampBits = 41;
private int ipBits = 16;
private int processIdBits = 18;
private int sequenceBits = 8;
@SuppressWarnings("unused")
private long maxTimestamp = -1L ^ (-1L << timestampBits);
private long maxIp = -1L ^ (-1L << ipBits);
private long maxProcessId = -1L ^ (-1L << processIdBits);
private long sequenceMask = -1L ^ (-1L << sequenceBits);
private int processIdShift = sequenceBits;
private int ipSfhit = sequenceBits + processIdBits;
private int timestampShift = sequenceBits + processIdBits + ipBits;
private long ip = 1L;
private long processId = 1L;
private long sequence = 1L;
private long lastTimestamp = 1L;
private final ReentrantLock lock = new ReentrantLock();
public Snowflake(String ipAddr) {
String[] ipArray = ipAddr.split("\\.");
ip = Long.valueOf(ipArray[2]) << 8 | Long.valueOf(ipArray[3]) & maxIp;
processId = Long.valueOf(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]) & maxProcessId;
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = 1L;
for (;;) {
timestamp = System.currentTimeMillis();
if (timestamp > lastTimestamp) {
return timestamp;
}
}
}
public String nextId() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
long timestamp = System.currentTimeMillis();
if (timestamp < TH_EPOCH) {
throw new RuntimeException("clock is moving backwards.Reject requests before epoch!");
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
long idLow = ip << ipSfhit | processId << processIdShift | sequence;
BigInteger idHign = BigInteger.valueOf(timestamp - TH_EPOCH).shiftLeft(timestampShift);
BigInteger id = idHign.add(BigInteger.valueOf(idLow));
return id.toString(10);
} finally {
lock.unlock();
}
}
public String nextIdHex() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
long timestamp = System.currentTimeMillis();
if (timestamp < TH_EPOCH) {
throw new RuntimeException("clock is moving backwards.Reject requests before epoch!");
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
long idLow = ip << ipSfhit | processId << processIdShift | sequence;
BigInteger idHign = BigInteger.valueOf(timestamp - TH_EPOCH).shiftLeft(timestampShift);
BigInteger id = idHign.add(BigInteger.valueOf(idLow));
return id.toString(16);
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
Snowflake snow = new Snowflake("188.89.56.123");
System.out.println(snow.nextId());
System.out.println(snow.nextId());
System.out.println(snow.nextId());
System.out.println(snow.nextId());
System.out.println(snow.nextId());
System.out.println(snow.nextId());
System.out.println(snow.nextId());
System.out.println(snow.nextId());
System.out.println(snow.nextIdHex());
System.out.println(snow.nextIdHex());
System.out.println(snow.nextIdHex());
System.out.println(snow.nextIdHex());
System.out.println(snow.nextIdHex());
System.out.println(snow.nextIdHex());
System.out.println(snow.nextIdHex());
System.out.println(snow.nextIdHex());
}
}