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: }
|