IdWorker

public class IdWorker {
// 時間起始標(biāo)記點(diǎn),作為基準(zhǔn),一般取系統(tǒng)的最近時間(一旦確定不能變動)
private final static long twepoch = 1288834974657L;
// 機(jī)器標(biāo)識位數(shù)
private final static long workerIdBits = 5L;
// 數(shù)據(jù)中心標(biāo)識位數(shù)
private final static long datacenterIdBits = 5L;
// 機(jī)器ID最大值
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
// 數(shù)據(jù)中心ID最大值
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
// 毫秒內(nèi)自增位
private final static long sequenceBits = 12L;
// 機(jī)器ID偏左移12位
private final static long workerIdShift = sequenceBits;
// 數(shù)據(jù)中心ID左移17位
private final static long datacenterIdShift = sequenceBits + workerIdBits;
// 時間毫秒左移22位
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
/* 上次生產(chǎn)id時間戳 */
private static long lastTimestamp = -1L;
// 0温艇,并發(fā)控制
private long sequence = 0L;

private final long workerId;
// 數(shù)據(jù)標(biāo)識id部分
private final long datacenterId;

public IdWorker(){
    this.datacenterId = getDatacenterId(maxDatacenterId);
    this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
}
/**
 * @param workerId
 *            工作機(jī)器ID
 * @param datacenterId
 *            序列號
 */
public IdWorker(long workerId, long datacenterId) {
    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;
}
/**
 * 獲取下一個ID
 *
 * @return
 */
public synchronized long nextId() {
    long timestamp = timeGen();
    if (timestamp < lastTimestamp) {
        throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
    }

    if (lastTimestamp == timestamp) {
        // 當(dāng)前毫秒內(nèi)竖伯,則+1
        sequence = (sequence + 1) & sequenceMask;
        if (sequence == 0) {
            // 當(dāng)前毫秒內(nèi)計數(shù)滿了沟娱,則等待下一秒
            timestamp = tilNextMillis(lastTimestamp);
        }
    } else {
        sequence = 0L;
    }
    lastTimestamp = timestamp;
    // ID偏移組合生成最終的ID铭污,并返回ID
    long nextId = ((timestamp - twepoch) << timestampLeftShift)
            | (datacenterId << datacenterIdShift)
            | (workerId << workerIdShift) | sequence;

    return nextId;
}

private long tilNextMillis(final long lastTimestamp) {
    long timestamp = this.timeGen();
    while (timestamp <= lastTimestamp) {
        timestamp = this.timeGen();
    }
    return timestamp;
}

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

/**
 * <p>
 * 獲取 maxWorkerId
 * </p>
 */
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
    StringBuffer mpid = new StringBuffer();
    mpid.append(datacenterId);
    String name = ManagementFactory.getRuntimeMXBean().getName();
    if (!name.isEmpty()) {
        /*
         * GET jvmPid
         */
        mpid.append(name.split("@")[0]);
    }
    /*
     * MAC + PID 的 hashcode 獲取16個低位
     */
    return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
}

/**
 * <p>
 * 數(shù)據(jù)標(biāo)識id部分
 * </p>
 */
protected static long getDatacenterId(long maxDatacenterId) {
    long id = 0L;
    try {
        InetAddress ip = InetAddress.getLocalHost();
        NetworkInterface network = NetworkInterface.getByInetAddress(ip);
        if (network == null) {
            id = 1L;
        } else {
            byte[] mac = network.getHardwareAddress();
            id = ((0x000000FF & (long) mac[mac.length - 1])
                    | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
            id = id % (maxDatacenterId + 1);
        }
    } catch (Exception e) {
        System.out.println(" getDatacenterId: " + e.getMessage());
    }
    return id;
}


public static void main(String[] args) {
    IdWorker idWorker = new IdWorker();
    long nextId = idWorker.nextId();
        System.out.println(nextId);



}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嗡官,一起剝皮案震驚了整個濱河市箭窜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌衍腥,老刑警劉巖磺樱,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異婆咸,居然都是意外死亡坊罢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門擅耽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來活孩,“玉大人,你說我怎么就攤上這事乖仇『度澹” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵乃沙,是天一觀的道長起趾。 經(jīng)常有香客問我,道長警儒,這世上最難降的妖魔是什么训裆? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任眶根,我火速辦了婚禮,結(jié)果婚禮上边琉,老公的妹妹穿的比我還像新娘属百。我一直安慰自己,他們只是感情好变姨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布族扰。 她就那樣靜靜地躺著,像睡著了一般定欧。 火紅的嫁衣襯著肌膚如雪渔呵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天砍鸠,我揣著相機(jī)與錄音扩氢,去河邊找鬼。 笑死爷辱,一個胖子當(dāng)著我的面吹牛录豺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播托嚣,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼巩检,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了示启?” 一聲冷哼從身側(cè)響起兢哭,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎夫嗓,沒想到半個月后迟螺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舍咖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年矩父,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片排霉。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡窍株,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出攻柠,到底是詐尸還是另有隱情球订,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布瑰钮,位于F島的核電站冒滩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏浪谴。R本人自食惡果不足惜开睡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一因苹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧篇恒,春花似錦扶檐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽官卡。三九已至蝗茁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寻咒,已是汗流浹背哮翘。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留毛秘,地道東北人饭寺。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像叫挟,于是被迫代替她去往敵國和親艰匙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容