IDFactory int类型ID生成器

这个名字老记不住,一到用的时候就想不起来,还得翻以前的项目各种找。。。

在此特此记录吧

  1 public class IDFactory {
  2 
  3     private static final Logger LOGGER = LoggerFactory.getLogger(IDFactory.class);
  4     /**
  5      * 使用Bitset标记所有已使用的id<br>
  6      * 不限定大小,以至于能达到 {@link Integer#MAX_VALUE}
  7      */
  8     private final BitSet idList;
  9 
 10     /**
 11      * 同步锁
 12      */
 13     private final ReentrantLock lock;
 14 
 15     /**
 16      * 标记下一个int的索引
 17      */
 18     private volatile int nextIndex = 0;
 19 
 20     private IDFactory() {
 21         idList = new BitSet();
 22         lock = new ReentrantLock();
 23         lockIds(0);
 24 
 25         LOGGER.info("IDFactory: " + getUsedCount() + " id's used.");
 26     }
 27 
 28     private static class SingletonHolder {
 29         protected static final IDFactory INSTANCE = new IDFactory();
 30     }
 31 
 32     public static final IDFactory getInstance() {
 33         return SingletonHolder.INSTANCE;
 34     }
 35 
 36     /**
 37      * 下一个可用的int值
 38      * 
 39      * @return
 40      */
 41     public int nextId() {
 42         try {
 43             lock.lock();
 44 
 45             int id;
 46             if (nextIndex == Integer.MIN_VALUE) {
 47                 id = Integer.MIN_VALUE;
 48             } else {
 49                 id = idList.nextClearBit(nextIndex);
 50             }
 51 
 52             // 当id超过Integer#MAX_VALUE后的下一个int值将是Integer#MIN_VALUE,即已经用光了
 53             if (id == Integer.MIN_VALUE) {
 54                 LOGGER.error("All id's are used!",new Exception("All id's are used!"));
 55             }
 56             idList.set(id);
 57 
 58             // It ok to have Integer OverFlow here, on next ID request IDFactory
 59             // will throw error
 60             nextIndex = id + 1;
 61             return id;
 62         } finally {
 63             lock.unlock();
 64         }
 65     }
 66 
 67     /**
 68      * 告诉生成器已使用了那些int值
 69      * 
 70      * @param ids
 71      *            ids to lock
 72      */
 73     private void lockIds(int... ids) {
 74         try {
 75             lock.lock();
 76             for (int id : ids) {
 77                 boolean status = idList.get(id);
 78                 if (status) {
 79                     LOGGER.error("ID " + id + " is already taken, fatal error!",new Exception("ID " + id + " is already taken, fatal error!"));
 80                 }
 81                 idList.set(id);
 82             }
 83         } finally {
 84             lock.unlock();
 85         }
 86     }
 87 
 88     /**
 89      * 告诉生成器已使用了那些int值
 90      * 
 91      * @param ids
 92      *            ids to lock
 93      */
 94     public void lockIds(Iterable<Integer> ids) {
 95         try {
 96             lock.lock();
 97             for (int id : ids) {
 98                 boolean status = idList.get(id);
 99                 if (status) {
100                     LOGGER.error("ID " + id + " is already taken, fatal error!",new Exception("ID " + id + " is already taken, fatal error!"));
101                 }
102                 idList.set(id);
103             }
104         } finally {
105             lock.unlock();
106         }
107     }
108 
109     /**
110      * 告诉生成器某int值可以重新使用
111      * 
112      * @param id
113      *            id to release
114      */
115     public void releaseId(int id) {
116         try {
117             lock.lock();
118             boolean status = idList.get(id);
119             if (!status) {
120                 LOGGER.error("ID " + id + " is not taken, can't release it.",new Exception("ID " + id + " is not taken, can't release it."));
121             }
122             idList.clear(id);
123             if (id < nextIndex || nextIndex == Integer.MIN_VALUE) {
124                 nextIndex = id;
125             }
126         } finally {
127             lock.unlock();
128         }
129     }
130 
131     /**
132      * 已使用的int数
133      * 
134      * @return 已使用的int数
135      */
136     public int getUsedCount() {
137         try {
138             lock.lock();
139             return idList.cardinality();
140         } finally {
141             lock.unlock();
142         }
143     }
144 }

最适合用他的场景就是游戏中各种物体怪物之类的id

 

posted @ 2015-07-28 16:58  韩宏敏  阅读(1713)  评论(0编辑  收藏  举报