java单例模式生成id_序列键生成器及单例多例模式

有时候我们希望生成全局唯一的序列号。可以用于生成主键或者生成全局的序列号用于生成编号或者其他。这时候我们可以用SQL语句自行管理键值。使用一个表来存储所有的键列值。如下表所示:

key

value

PO_NUMBER

105

SE_NUMBER

2555

...

...

1.  存储方式:

预定式键值存储:在预定一个值时首先将值更新为下一个可用值,然后查出来之后提供给客户端使用。这样万一出现中断的话顶多是浪费这几个键值。每次可以预定多个键值(也就是一个键值区间)而不是一个值,也就是更新键值的时候将键值增加大于1的数目。这么做可以避免多次访问数据库。

记录式键值存储:也就是说,键值首先被返还给客户端,然后记录到数据库中取。这样做的缺点是:一旦系统出现中断,就可能出现客户端已经使用了一个键值,而这个键值却没有来得及存储到数据库中。在系统重启之后,系统还会从这个已经被使用过的键值开始,从而导致错误。

2.单例模式与多例模式的应用

单例模式:

可以用单例模式来实现,整个系统只有一个序列键值管理器来管理序列号。

多例模式:

多例类往往持有一个内蕴状态(内蕴状态是存储在享元对象内部并且不会随环境的改变而改变),多例类的每一个实例都有独特的内蕴状态。一个多例类持有一个集合对象,用来登记自身的实例,而其内蕴状态往往就是登记的键值。当客户端通过多例类的静态工厂方法请求多例类的实例时,这个工厂方法都会在集合内查询是否有这样的一个实例。如果有直接返回给客户端;如果没有就创建一个这样的实例,并登记到集合中,然后返回给客户端。如下:

键名为内蕴状态;键名和自身作为map的key和value存入集合中。

packagecn.qlq.singleton;importjava.util.concurrent.ConcurrentHashMap;public classKeyGenerator {//多例模式应用

private static ConcurrentHashMap keyGenerators = new ConcurrentHashMap<>();privateKeyGenerator(String key) {//用key做处理

}/*** 静态工厂方法提供自己的实例

*

*@return

*/

public staticKeyGenerator getInstance(String keyName) {if(keyGenerators.containsKey(keyName)) {returnkeyGenerators.get(keyName);

}

KeyGenerator keyGenerator= newKeyGenerator(keyName);

keyGenerators.put(keyName, keyGenerator);returnkeyGenerator;

}

}

3.  单例模式应用

1.没有数据库的情况

首先不使用数据库,用一个成员属性模拟键值。如下:

packagecn.qlq;importjava.util.concurrent.ConcurrentHashMap;/*** 单例模式的唯一值生成器

*

*@authorQiaoLiQiang

* @time 2019年6月12日下午10:39:42*/

public classKeyGenerator {/*** 存放key、value*/

private ConcurrentHashMap values = new ConcurrentHashMap<>();private static KeyGenerator keyGenerator = newKeyGenerator();privateKeyGenerator() {//防止反射创建实例

if (keyGenerator != null) {throw new RuntimeException("not allowed!");

}

}/*** 静态工厂方法提供自己的实例

*

*@return

*/

public staticKeyGenerator getInstance() {returnkeyGenerator;

}/*** 获取下一个序列制

*

*@paramkey

* 序列的键

*@return自增后的值*/

public synchronized intgetNextKey(String key) {//如果存在就加1且返回

if(values.containsKey(key)) {

Integer nextValue= values.get(key) + 1;

values.put(key, nextValue);returnnextValue;

}//初始化

Integer startValue = 1;

values.put(key, startValue);returnstartValue;

}

}

测试代码:(两个线程使用序列生成器)

packagecn.qlq;importjava.util.concurrent.CountDownLatch;public classMainClass {public static void main(String[] args) throwsInterruptedException {//制造一个闭锁

final CountDownLatch countDownLatch = new CountDownLatch(2);//模拟使用序列生成器

for (int i = 0; i < 2; i++) {new Thread(newRunnable() {

@Overridepublic voidrun() {for (int j = 0; j < 4; j++) {

String key= j % 2 + "";

System.out.println(key+ "\t" +Ke

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值