001: /*
002: * JFox - The most lightweight Java EE Application Server!
003: * more details please visit http://www.huihoo.org/jfox or http://www.jfox.org.cn.
004: *
005: * JFox is licenced and re-distributable under GNU LGPL.
006: */
007: package org.jfox.entity.dao;
008:
009: import java.text.SimpleDateFormat;
010: import java.util.concurrent.locks.Lock;
011: import java.util.concurrent.locks.ReentrantLock;
012: import java.util.Date;
013: import java.util.Map;
014: import java.util.HashMap;
015:
016: /**
017: * 用�生�唯一的PK
018: * 该 PK 生�器生� 19 �的唯一 long 值,精确到万分之一秒,
019: * 最�一�为尾数,用�在集群环境下��PK的唯一性。
020: *
021: * 该PK生æˆ?虽然ä¾?赖于时间,但是在è¿?行过程ä¸æ”¹å?˜æ—¶é—´ä¸?会影å“?PK,
022: * 但是如果将系统时间å?Žè°ƒï¼Œç„¶å?Žé‡?æ–°å?¯åŠ¨ï¼Œæœ‰å?¯èƒ½é€ æˆ?PKé‡?å¤?。
023: *
024: * 该 PK 生�器��赖于数�库,相比�赖数�表的PK生�器,速度快,而且值�读
025: *
026: * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
027: */
028: public class PKGenerator {
029: /**
030: * PK生��,用��定�一时刻�有一个线程进入PK生�计算
031: */
032: private final Lock LOCK = new ReentrantLock();
033:
034: /**
035: * åˆ?å§‹åŒ–æ—¶çš„æ¯«ç§’æ•°ï¼Œå› ä¸ºè¯¥æ—¶é—´ä¼šéš?系统时间的改å?˜è€Œæ”¹å?˜ï¼Œ
036: * æ‰€ä»¥è®¡ç®—æ–¹æ³•ä¸ºè¯¥æ—¶é—´åŠ ä¸Šé€šè¿‡ nanoTime 计算出æ?¥çš„时间差
037: */
038: private final static Long startMilli = System.currentTimeMillis();
039:
040: /**
041: * �始化时的纳秒数,用�计�时间差,nanoTime�会��系统时间的修改而改�
042: */
043: private final static long startNano = System.nanoTime();
044:
045: /**
046: * 记录上一次生æˆ? çš„ PK,如果新生æˆ?çš„PK和上次相ç‰ï¼Œåˆ™éœ€è¦?å†?次生æˆ?
047: */
048: private volatile long lastPK = -1;
049:
050: private final static SimpleDateFormat dateFormat = new SimpleDateFormat(
051: "yyyyMMddHHmmssSSS");
052:
053: /**
054: * 返回的long PK的尾数,尾数å?¯ä»¥ç”¨æ?¥åœ¨é›†ç¾¤çŽ¯å¢ƒä¸åˆ¤æ–该PK由哪一个节点产生
055: * 尾数通过�置设定
056: */
057: private int suffix = 0;
058:
059: private static final Map<Integer, PKGenerator> instanceMap = new HashMap<Integer, PKGenerator>();
060:
061: //å¿…é¡»æ??ä¾›æ£ç¡®çš„å?‚数,以ä¿?è¯? suffix 在机群环境的唯一性
062: private PKGenerator(int suffix) {
063: this .suffix = suffix;
064: }
065:
066: public synchronized static PKGenerator getInstance() {
067: return getInstance(0);
068: }
069:
070: /**
071: * �机环境下,应该��用相�的 suffix
072: *
073: * 在集群环境ä¸ï¼Œä¸?å?Œçš„机器必须æ??ä¾›ä¸?å?Œçš„ suffix æ?¥ä¿?è¯?生æˆ?çš„ID的唯一性
074: *
075: * @param suffix å”¯ä¸€æ ‡è¯†å¥½
076: */
077: public synchronized static PKGenerator getInstance(int suffix) {
078: PKGenerator pkgen;
079: if (!instanceMap.containsKey(suffix)) {
080: pkgen = new PKGenerator(suffix);
081: instanceMap.put(suffix, pkgen);
082: } else {
083: pkgen = instanceMap.get(suffix);
084: }
085: return pkgen;
086: }
087:
088: /**
089: * 返回下一个 long 型 PK, format: 2006111423361344491 <br>
090: * yyyyMMddHHmmssSSS + Macro Seconds + suffix
091: *
092: * @return long PK
093: */
094: public long nextPK() {
095: LOCK.lock();
096: try {
097: long newPK;
098: do {
099: long pastNano = System.nanoTime() - startNano; // 纳秒时间差
100: long milliTime = pastNano / 1000000; // �得毫秒差
101: long macroTime = (pastNano / 100000) % 10; // �得微秒第一�,
102: // 计算出æ?¥çš„long PKï¼Œç²¾åº¦åˆ°ä¸‡åˆ†ä¹‹ä¸€ç§’ï¼ˆç™¾å¾®å¦™ï¼‰ï¼ŒåŠ ä¸Šå°¾æ•°ï¼Œä¸€å…±19ä½?,这是 Long.MAX_VALUE的最大ä½?数了
103: newPK = Long.parseLong(dateFormat.format(new Date(
104: startMilli + milliTime))
105: + macroTime + suffix);
106: } while (lastPK == newPK); // 如果生�的相�,则�次计算
107: lastPK = newPK; // 设置 lastPK
108: return newPK;
109: } finally {
110: LOCK.unlock();
111: }
112: }
113:
114: public static void main(String[] args) throws Exception {
115: PKGenerator pkg = getInstance(0);
116: int i = 0;
117: long now = System.currentTimeMillis();
118: while (i++ < 1000) {
119: System.out.println(pkg.nextPK());
120: }
121: System.out.println("Time: "
122: + (System.currentTimeMillis() - now));
123: }
124: }
|