Java生成32位全局唯一id

本文介绍了一种基于Java的32位全局唯一ID生成方案,该方案利用系统时间、IP地址、线程HashCode和随机数来确保ID的全局唯一性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结。生成ID的方法有很多,适应不同的场景、需求以及性能要求。这里说一下用java生成32位全局唯一id的实现过程。


主要实现思路是:14位的当前系统时间(格式为:yyyyMMddHHmmss) + 当前电脑的IP地址的最后两位 + 当前线程的hashCode的前9位 + 7位的随机数


一、相关实现代码

工具类实现代码如下:

package com.test;

import java.io.IOException;
import java.net.InetAddress;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.lang.StringUtils;

/** 
 * @ClassName: UniqId 
 * @Description: 生成32位全局唯一id
 */
public class UniqId {
	
	private static UniqId me = new UniqId();
    private String hostAddr;
    private final Random random = new SecureRandom();
    private final UniqTimer timer = new UniqTimer();
    
    private boolean isOutputInfo = false;
    
    private UniqId() {
        try {
            final InetAddress addr = InetAddress.getLocalHost();

            hostAddr = addr.getHostAddress();
        }
        catch (final IOException e) {
            System.err.println("[UniqID] Get HostAddr Error"+e);
            hostAddr = String.valueOf(System.currentTimeMillis());
        }

        if (null == hostAddr || hostAddr.trim().length() == 0 || "127.0.0.1".equals(hostAddr)) {
            hostAddr = String.valueOf(System.currentTimeMillis());
            
        }
        hostAddr = hostAddr.substring(hostAddr.length()-2).replace(".", "0");
        
        if(isOutputInfo){
        	System.out.println("[UniqID]hostAddr is:" + hostAddr + "----length:"+hostAddr.length());
        }
    }
    
    
    /**
     * 获取UniqID实例
     * 
     * @return UniqId
     */
    public static UniqId getInstance() {
    	me.isOutputInfo = false;
        return me;
    }
    
    /**
     * 获取UniqID实例
     * 
     * @return UniqId
     */
	public static UniqId getInstanceWithLog() {
    	me.isOutputInfo = true;
        return me;
    }


    /**
     * 获得不会重复的毫秒数
     * 
     * @return 不会重复的时间
     */
    public String getUniqTime() {
    	String time = timer.getCurrentTime();
    	if(isOutputInfo){
    		System.out.println("[UniqID.getUniqTime]" + time +"----length:"+ time.length());
    	}
        return time;
    }
    
    /**
     * 获得UniqId
     * 
     * @return uniqTime-randomNum-hostAddr-threadId
     */
    public String getUniqID() {
        final StringBuffer sb = new StringBuffer();
        final String t = getUniqTime();
        int randomNumber = random.nextInt(8999999) + 1000000;
        sb.append(t);
        sb.append(hostAddr);
        sb.append(getUniqThreadCode());
        sb.append(randomNumber);
        if (isOutputInfo) {
            System.out.println("[UniqID.randomNumber]" + randomNumber+"----length:"+String.valueOf(randomNumber).length());
            System.out.println("[UniqID.getUniqID]" + sb.toString()+"----length:"+String.valueOf(sb).length());
        }
        return sb.toString();
    }
    
    public String getUniqThreadCode(){
    	String threadCode = StringUtils.left(String.valueOf(Thread.currentThread().hashCode()),9);
    	if (isOutputInfo) {
            System.out.println("[UniqID.getUniqThreadCode]" +threadCode+"----length:"+threadCode.length());
        }
    	return StringUtils.leftPad(threadCode, 9, "0");
    }
    
    /**
     * 实现不重复的时间
     */
    private class UniqTimer {
        private final AtomicLong lastTime = new AtomicLong(System.currentTimeMillis());

        public String getCurrentTime() {
        	if(!timestamp2Date(this.lastTime.incrementAndGet()).equals(timestamp2Date(System.currentTimeMillis()))){
        		lastTime.set(System.currentTimeMillis()+random.nextInt(10000));
        	}
        	return timestamp2Datetimes(this.lastTime.incrementAndGet());
        }
    }
    
    /**
	 * 规范化日期,规范成yyyy-MM-dd
	 * @param timestamp
	 * @return
	 */
	public static String timestamp2Date(long timestamp){
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		return dateFormat.format(new Date(timestamp * 1000));
	}
    
	private static String timestamp2Datetimes(long timestamp){
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		return dateFormat.format(new Date(timestamp));
	}
    
}


测试代码如下:

package com.test;

public class test {
	public static void main(String[] args) {
		//打印生成过程
		UniqId.getInstanceWithLog().getUniqID();
		
		//建议如下使用
//		String uid = UniqId.getInstance().getUniqID();
//		System.out.println(uid);
//		System.out.println(uid.length());

	}
}

二、jar包依赖

上述代码依赖org.apache.commons.lang.StringUtils,介绍如下两种依赖的方式:

方式一:Maven项目的依赖

如果你的项目是maven项目,那么请确保项目的pom.xml有如下依赖:

	<dependency>
	      <groupId>commons-lang</groupId>
	      <artifactId>commons-lang</artifactId>
	      <version>2.3</version>
	 </dependency>

方式二:普通java项目的引用

(1)如果你是一个普通的java工程,那么请将commons-lang-2.3.jar拷贝至你的工程,并添加到编译环境

(2)如果你是一个普通的javaWeb工程,那么直接将commons-lang-2.3.jar拷贝至工程的WEB-INF\lib下即可编译通过。

这里提供一下我个人的百度云存储commons-lang-2.3.jar的链接地址:

链接:https://pan.baidu.com/s/1c2qAx7y 密码:r9dr

当然你也可以从网上下载commons-lang的其他版本。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值