• 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

  • 相关阅读:
    啥叫ORM
    git reset --hard HEAD^ 在cmd中执行报错
    windows下生成文件目录树
    批量解决win10图标上有两个蓝色箭头的方法
    Sublime Text 3 安装包
    Sublime Text 3 部分安装过程记录
    sense8影评摘抄
    如何取消chrome的自动翻译
    把本地仓库同步到github上去
    关于PDF阅读器
  • 原文地址:https://www.cnblogs.com/hanhongmin/p/4683417.html
Copyright © 2020-2023  润新知