1. 程式人生 > >Java 的 ID 生成器(工具類)

Java 的 ID 生成器(工具類)

使用業務場景
1. 資料庫自增主鍵無法滿足
2. 分散式系統的ID生成
3. 需要按照時間生成唯一ID
4. 無序的唯一ID

import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.util.UUID;

/**
 *  用於生產各種各樣的ID
 */
public class IdUtils {

    private
static String middle = ""; static { middle = MathUtils.makeUpNewData(Math.abs(NetworkUtils.getHostIP().hashCode()) + "", 4) + //4位IP地址hash MathUtils.makeUpNewData(NetworkUtils.getPid(), 4); //4位PID程序hash } /** * 以毫微秒做基礎計數, 返回唯一有序增長ID * <pre>System.nanoTime()</pre> * <pre> * 執行緒數量: 100 * 執行次數: 1000 * 平均耗時: 222 ms * 陣列長度: 100000 * Map Size: 100000 * </pre> * @return
ID長度32位 */
public static String getIncreaseIdByNanoTime(){ return System.nanoTime()+ //時間戳-14位 middle+ //標誌-8位 MathUtils.makeUpNewData(Thread.currentThread().hashCode()+""
, 3)+ //3位執行緒標誌 MathUtils.randomDigitNumber(7); //隨機7位數 } /** * 以毫秒做基礎計數, 返回唯一有序增長ID, 有機率出現執行緒併發 * <pre>System.currentTimeMillis()</pre> * <pre> * 執行緒數量: 100 * 執行次數: 1000 * 平均耗時: 206 ms * 陣列長度: 100000 * Map Size: 99992 * </pre> * @return ID長度32位 */ public static String getIncreaseIdByCurrentTimeMillis(){ return System.currentTimeMillis()+ //時間戳-14位 middle+ //標誌-8位 MathUtils.makeUpNewData(Thread.currentThread().hashCode()+"", 3)+ //3位執行緒標誌 MathUtils.randomDigitNumber(8); //隨機8位數 } /** * 基於UUID+MD5產生唯一無序ID * <pre> * 執行緒數量: 100 * 執行次數: 1000 * 平均耗時: 591 ms * 陣列長度: 100000 * Map Size: 100000 * </pre> * @return ID長度32位 */ public static String getRandomIdByUUID(){ return DigestUtils.md5Hex(UUID.randomUUID().toString()); } /* ---------------------------------------------分割線------------------------------------------------ */ /** 字串MD5處理類 */ private static class DigestUtils { private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; private static char[] encodeHex(final byte[] data, final char[] toDigits) { final int l = data.length; final char[] out = new char[l << 1]; for (int i = 0, j = 0; i < l; i++) { out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; out[j++] = toDigits[0x0F & data[i]]; } return out; } public static String md5Hex(String str){ return md5Hex(str, false); } public static String md5Hex(String str, boolean isUpper){ try { return new String(encodeHex(MessageDigest.getInstance("MD5").digest(str.getBytes("UTF-8")), isUpper ? DIGITS_UPPER : DIGITS_LOWER)); } catch (Exception e) { throw new RuntimeException(e); } } } /* ---------------------------------------------分割線------------------------------------------------ */ /** 網路相關的處理類 */ private static class NetworkUtils { private static final String DEFAULT_HOST_IP = "10.10.10.10"; /** * 獲取當前程序的PID */ public static String getPid(){ return ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; } /** * 獲取當前程序的主機IP地址 */ public static String getHostIP(){ try { return InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { return DEFAULT_HOST_IP; } } } /* ---------------------------------------------分割線------------------------------------------------ */ /** 資料處理的相關類 */ private static class MathUtils { private static final String DEFAULT_DIGITS = "0"; private static final String FIRST_DEFAULT_DIGITS = "1"; /** * @param target 目標數字 * @param length 需要補充到的位數, 補充預設數字[0], 第一位預設補充[1] * @return 補充後的結果 */ public static String makeUpNewData(String target, int length){ return makeUpNewData(target, length, DEFAULT_DIGITS); } /** * @param target 目標數字 * @param length 需要補充到的位數 * @param add 需要補充的數字, 補充預設數字[0], 第一位預設補充[1] * @return 補充後的結果 */ public static String makeUpNewData(String target, int length, String add){ if(target.startsWith("-")) target.replace("-", ""); if(target.length() >= length) return target.substring(0, length); StringBuffer sb = new StringBuffer(FIRST_DEFAULT_DIGITS); for (int i = 0; i < length - (1 + target.length()); i++) { sb.append(add); } return sb.append(target).toString(); } /** * 生產一個隨機的指定位數的字串數字 * @param length * @return */ public static String randomDigitNumber(int length){ int start = Integer.parseInt(makeUpNewData("", length));//1000+8999=9999 int end = Integer.parseInt(makeUpNewData("", length + 1)) - start;//9000 return (int)(Math.random() * end) + start + ""; } } }