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
我是cocos2dx初学者,Java5年,一点C++,OC经验都没有,各位见笑了
文章中如有错误或者不全面或者有更好的解决办法,请指出,不胜感激