java唯一订单号生成

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class IdWorker {
	protected static final Logger LOG = LoggerFactory.getLogger(IdWorker.class);

	/**
	 * 每个节点的唯一数字ID
	 */
	private long workerId;

	private long datacenterId;

	private long sequence = 0L;

	private long twepoch = 1288834974657L;

	// 机器标识位数
	private long workerIdBits = 5L;

	// 数据中心标识位数
	private long datacenterIdBits = 5L;

	// 机器ID最大值
	private long maxWorkerId = -1L ^ (-1L << workerIdBits);

	// 数据中心ID最大值
	private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

	// 毫秒内自增位
	private long sequenceBits = 12L;

	// 机器ID偏左移12位
	private long workerIdShift = sequenceBits;

	// 数据中心ID左移17位
	private long datacenterIdShift = sequenceBits + workerIdBits;

	// 时间毫秒左移22位
	private long timestampLeftShift = sequenceBits + workerIdBits+ datacenterIdBits;

	private long sequenceMask = -1L ^ (-1L << sequenceBits);

	private long lastTimestamp = -1L;

	public IdWorker(final long workerId) {
		super();
		if (workerId > this.maxWorkerId || workerId < 0) {
			throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0",maxWorkerId));
		}

		this.workerId = workerId;
	}

	public IdWorker(long workerId, long datacenterId) {
		// sanity check for workerId
		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;

		LOG.info(String.format("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d",timestampLeftShift, datacenterIdBits, workerIdBits,sequenceBits, workerId));
	}

	public synchronized long nextId() {
		long timestamp = timeGen();
		if (timestamp < lastTimestamp) {
			LOG.error(String.format("clock is moving backwards.  Rejecting requests until %d.",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
		return ((timestamp - twepoch) << timestampLeftShift)| (datacenterId << datacenterIdShift)| (workerId << workerIdShift) | sequence;
	}

	// 等待下一个毫秒的到来

	protected long tilNextMillis(long lastTimestamp) {
		long timestamp = timeGen();
		while (timestamp <= lastTimestamp) {
			timestamp = timeGen();
		}
		return timestamp;
	}

	protected long timeGen() {
		return System.currentTimeMillis();
	}
	
	public static void main(String[] args) {
		IdWorker idWorker = new IdWorker(1);
		long orderId = idWorker.nextId();
		System.out.println(orderId);
	}
}

还有另外一种方式使用用户的编号+时间戮

http://www.oschina.net/question/865233_2137987 

snowflake忽然想到一个问题,不能随便调整服务器的时间

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.Random;

/**
 * 在分布式系统中,需要生成全局UID的场合还是比较多的,twitter的snowflake解决了这种需求,
 * 实现也还是很简单的,除去配置信息,核心代码就是毫秒级时间41位+机器ID 10位+毫秒内序列12位。
 * 该项目地址为:https://github.com/twitter/snowflake是用Scala实现的。
 * Created by Administrator on 2016/3/31.
 */
public class IdWorker {
    /**
     * 根据具体机器环境提供
     */
    private final long workerId;

    /**
     * 滤波器,使时间变小,生成的总位数变小,一旦确定不能变动
     */
    private final static long twepoch = 1361753741828L;

    private long sequence = 0L;

    private final static long workerIdBits = 10L;

    private final static long maxWorkerId = -1L ^ -1L << workerIdBits;

    private final static long sequenceBits = 12L;

    private final static long workerIdShift = sequenceBits;

    private final static long timestampLeftShift = sequenceBits + workerIdBits;

    private final static long sequenceMask = -1L ^ -1L << sequenceBits;

    private long lastTimestamp = -1L;

    /**
     * 主机和进程的机器码
     */
    private static IdWorker worker = new IdWorker();

    private static final Log logger = LogFactory.getLog(IdWorker.class);

    /**
     * 主机和进程的机器码
     */
    private static final int _genmachine;


    static {
        try {
            // build a 2-byte machine piece based on NICs info
            int machinePiece;
            {
                try {
                    StringBuilder sb = new StringBuilder();
                    Enumeration<NetworkInterface> 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.error(" IdWorker error. ", e);
                    machinePiece = new Random().nextInt() << 16;
                }
                logger.debug("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 = IdWorker.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.debug("process piece: " + Integer.toHexString(processPiece));
            }

            _genmachine = machinePiece | processPiece;
            logger.debug("machine : " + Integer.toHexString(_genmachine));
        } catch ( Exception e ) {
            throw new RuntimeException(e);
        }

    }


    public IdWorker() {
        workerId = _genmachine % (IdWorker.maxWorkerId + 1);
    }


    public static long getId() {
        return worker.nextId();
    }


    public synchronized long nextId() {
        long timestamp = timeGen();
        if ( lastTimestamp == timestamp ) {
            sequence = sequence + 1 & IdWorker.sequenceMask;
            if ( sequence == 0 ) {
                // System.out.println("###########" + sequenceMask);//等待下一毫秒
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0;
        }
        if ( timestamp < lastTimestamp ) {
            try {
                throw new Exception(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds",
                        lastTimestamp - timestamp));
            } catch ( Exception e ) {
                logger.error(" IdWorker error. ", e);
            }
        }

        lastTimestamp = timestamp;
        return timestamp - twepoch << timestampLeftShift | workerId << IdWorker.workerIdShift | sequence;
    }


    private long tilNextMillis( final long lastTimestamp1 ) {
        long timestamp = timeGen();
        while ( timestamp <= lastTimestamp1 ) {
            timestamp = timeGen();
        }
        return timestamp;
    }


    private long timeGen() {
        return System.currentTimeMillis();
    }
}

转载于:https://my.oschina.net/chaun/blog/387635

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值