java id生成器 分布式_分布式ID生成器

import com.google.common.base.Objects;

import java.net.NetworkInterface;

import java.nio.ByteBuffer;

import java.util.Date;

import java.util.Enumeration;

import java.util.Random;

import java.util.concurrent.atomic.AtomicInteger;

import java.util.logging.Level;

import java.util.logging.Logger;

/**

*

A globally unique identifier for objects.

*

*

Consists of 12 bytes, divided as follows:

*

*

ObjectID layout

*

*

01234567891011

*

*

*

timemachine pidinc

*

*

*

*

Instances of this class are immutable.

*/

public class ObjectId implements Comparable, java.io.Serializable{

private final int _time;

private final int _machine;

private final int _inc;

private boolean _new;

private static final int _genmachine;

private static AtomicInteger _nextInc = new AtomicInteger((new java.util.Random()).nextInt());

private static final long serialVersionUID = -4415279469780082174L;

private static final Logger LOGGER = Logger.getLogger("org.bson.ObjectId");

/**

* Create a new object id.

*/

public ObjectId(){

_time = (int) (System.currentTimeMillis() / 1000);

_machine = _genmachine;

_inc = _nextInc.getAndIncrement();

_new = true;

}

/**

* Gets a new object id.

*

* @return the new id

*/

public static ObjectId get(){

return new ObjectId();

}

/**

* Checks if a string could be an {@code ObjectId}.

*

* @param s a potential ObjectId as a String.

* @return whether the string could be an object id

* @throws IllegalArgumentException if hexString is null

*/

public static boolean isValid(String s){

if (s == null)

return false;

final int len = s.length();

if (len != 24)

return false;

for (int i = 0; i < len; i++) {

char c = s.charAt(i);

if (c >= '0' && c <= '9')

continue;

if (c >= 'a' && c <= 'f')

continue;

if (c >= 'A' && c <= 'F')

continue;

return false;

}

return true;

}

/**

* Converts this instance into a 24-byte hexadecimal string representation.

*

* @return a string representation of the ObjectId in hexadecimal format

*/

public String toHexString(){

final StringBuilder buf = new StringBuilder(24);

for (final byte b : toByteArray()) {

buf.append(String.format("%02x", b & 0xff));

}

return buf.toString();

}

/**

* Convert to a byte array. Note that the numbers are stored in big-endian order.

*

* @return the byte array

*/

public byte[] toByteArray() {

byte b[] = new byte[12];

ByteBuffer bb = ByteBuffer.wrap(b);

// by default BB is big endian like we need

bb.putInt(_time);

bb.putInt(_machine);

bb.putInt(_inc);

return b;

}

private int _compareUnsigned(int i, int j){

long li = 0xFFFFFFFFL;

li = i & li;

long lj = 0xFFFFFFFFL;

lj = j & lj;

long diff = li - lj;

if (diff < Integer.MIN_VALUE)

return Integer.MIN_VALUE;

if (diff > Integer.MAX_VALUE)

return Integer.MAX_VALUE;

return (int) diff;

}

public int compareTo(ObjectId id){

if (id == null)

return -1;

int x = _compareUnsigned(_time, id._time);

if (x != 0)

return x;

x = _compareUnsigned(_machine, id._machine);

if (x != 0)

return x;

return _compareUnsigned(_inc, id._inc);

}

/**

* Gets the timestamp (number of seconds since the Unix epoch).

*

* @return the timestamp

*/

public int getTimestamp(){

return _time;

}

/**

* Gets the timestamp as a {@code Date} instance.

*

* @return the Date

*/

public Date getDate(){

return new Date(_time * 1000L);

}

/**

* Gets the current value of the auto-incrementing counter.

*

* @return the current counter value.

*/

public static int getCurrentCounter(){

return _nextInc.get();

}

static {

try {

// build a 2-byte machine piece based on NICs info

int machinePiece;

{

try {

StringBuilder sb = new StringBuilder();

Enumeration e = NetworkInterface.getNetworkInterfaces();

while (e.hasMoreElements()) {

NetworkInterface ni = e.nextElement();

sb.append(ni.toString());

}

machinePiece = sb.toString().hashCode() << 16;

} catch (Throwable e) {

// exception sometimes happens with IBM JVM, use random

LOGGER.log(Level.WARNING, e.getMessage(), e);

machinePiece = (new Random().nextInt()) << 16;

}

LOGGER.fine("machine piece post: " + Integer.toHexString(machinePiece));

}

// add a 2 byte process piece. It must represent not only the JVM but the class loader.

// Since static var belong to class loader there could be collisions otherwise

final int processPiece;

{

int processId = new java.util.Random().nextInt();

try {

processId = java.lang.management.ManagementFactory.getRuntimeMXBean().getName().hashCode();

} catch (Throwable t) {

}

ClassLoader loader = ObjectId.class.getClassLoader();

int loaderId = loader != null ? System.identityHashCode(loader) : 0;

StringBuilder sb = new StringBuilder();

sb.append(Integer.toHexString(processId));

sb.append(Integer.toHexString(loaderId));

processPiece = sb.toString().hashCode() & 0xFFFF;

LOGGER.fine("process piece: " + Integer.toHexString(processPiece));

}

_genmachine = machinePiece | processPiece;

LOGGER.fine("machine : " + Integer.toHexString(_genmachine));

} catch (Exception e) {

throw new RuntimeException(e);

}

}

@Override

public boolean equals(Object o){

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

ObjectId that = (ObjectId) o;

return Objects.equal(this.serialVersionUID, that.serialVersionUID) &&

Objects.equal(this.LOGGER, that.LOGGER) &&

Objects.equal(this._time, that._time) &&

Objects.equal(this._machine, that._machine) &&

Objects.equal(this._inc, that._inc) &&

Objects.equal(this._new, that._new) &&

Objects.equal(this._nextInc, that._nextInc) &&

Objects.equal(this._genmachine, that._genmachine);

}

@Override

public int hashCode(){

return Objects.hashCode(serialVersionUID, LOGGER, _time, _machine, _inc, _new,

_nextInc, _genmachine);

}

public static void main(String[] args){

System.out.println(new ObjectId().toHexString());

System.out.println(new ObjectId().toHexString());

System.out.println(new ObjectId().toHexString());

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值