Java生成32位全局唯一id

系統唯一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的其他版本。



發佈了27 篇原創文章 · 獲贊 62 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章