当前位置: 首页 > news >正文

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

 

转载于:https://www.cnblogs.com/hanhongmin/p/4683417.html

相关文章:

  • SharePoint 2013 内容部署报错
  • 如何在CentOS6.5中进行PPPOE拨号上网
  • Ubuntu下安装Atom及使用
  • PHP读取超大文件的实例代码
  • YxdIOCP (DIOCP修改版)
  • ocp-051-3
  • java实现多线程的三种方式
  • ava垃圾加收机制和ios的arc有什么区别
  • Linux iostat命令详解
  • 建立完整的单向动态链表(包括初始化、创建、插入、删除、查找、销毁、输出)...
  • 【Go】Linux下使用Sublime Text搭建开发环境
  • 双nginx(主备、主主)反向代理tomcat实现web端负载均衡
  • c# 笔试题及参考答案大全
  • 如果有一天你没有了动力,可以看看
  • winsock 收发广播包
  • Angular数据绑定机制
  • CSS魔法堂:Absolute Positioning就这个样
  • css选择器
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • EOS是什么
  • github从入门到放弃(1)
  • Git初体验
  • miaov-React 最佳入门
  • Mithril.js 入门介绍
  • mongodb--安装和初步使用教程
  • node.js
  • spring-boot List转Page
  • 简单实现一个textarea自适应高度
  • 使用 QuickBI 搭建酷炫可视化分析
  • 7行Python代码的人脸识别
  • # 飞书APP集成平台-数字化落地
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (十六)一篇文章学会Java的常用API
  • (转) RFS+AutoItLibrary测试web对话框
  • (转)编辑寄语:因为爱心,所以美丽
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .gitignore文件设置了忽略但不生效
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .NET Reactor简单使用教程
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .NET 事件模型教程(二)
  • .net 无限分类
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • /bin/bash^M: bad interpreter: No such file or directory
  • @require_PUTNameError: name ‘require_PUT‘ is not defined 解决方法
  • [.net] 如何在mail的加入正文显示图片
  • []新浪博客如何插入代码(其他博客应该也可以)
  • [Android]常见的数据传递方式
  • [AR]Vumark(下一代条形码)