Java线程安全的计数器简单实现代码示例
前几天工作中一段业务代码需要一个变量每天从1开始递增。为此自己简单的封装了一个线程安全的计数器,可以让一个变量每天从1开始递增。当然了,如果项目在运行中发生重启,即便日期还是当天,还是会从1开始重新计数。所以把计数器的值存储在数据库中会更靠谱,不过这不影响这段代码的价值,现在贴出来,供有需要的人参考。
packagecom.hikvision.cms.rvs.common.util; importjava.text.SimpleDateFormat; importjava.util.ArrayList; importjava.util.Date; importjava.util.List; importjava.util.concurrent.CountDownLatch; importjava.util.concurrent.atomic.AtomicInteger; importjava.util.concurrent.atomic.AtomicReferenceFieldUpdater; /** *Createdbylihong10on2017/8/9. *一个循环计数器,每天从1开始计数,隔天重置为1。 *可以创建一个该类的全局对象,然后每次使用时候调用其get方法即可,可以保证线程安全性 */ publicclassCircularCounter{ privatestaticfinalAtomicReferenceFieldUpdatervalueUpdater= AtomicReferenceFieldUpdater.newUpdater(CircularCounter.class,AtomicInteger.class,"value"); //保证内存可见性 privatevolatileStringkey; //保证内存可见性 privatevolatileAtomicIntegervalue; privatestaticfinalStringDATE_PATTERN="yyyy-MM-dd"; publicCircularCounter(){ /** *这里将key设置为getCurrentDateString()+"sssssssssss"是为了测试addAndGet()方法中日期发生变化的情况 *正常使用应该将key初始化为getCurrentDateString() */ this.key=getCurrentDateString()+"sssssssssss"; this.value=newAtomicInteger(0); } /** *获取计数器加1以后的值 * *@return */ publicIntegeraddAndGet(){ AtomicIntegeroldValue=value; AtomicIntegernewInteger=newAtomicInteger(0); intnewVal=-1; StringnewDateStr=getCurrentDateString(); //日期一致,计数器加1后返回 if(isDateEquals(newDateStr)){ newVal=add(1); returnnewVal; } //日期不一致,保证有一个线程重置技术器 reSet(oldValue,newInteger,newDateStr); this.key=newDateStr; //重置后加1返回 newVal=add(1); returnnewVal; } /** *获取计数器的当前值 *@return */ publicIntegerget(){ returnvalue.get(); } /** *判断当前日期与老的日期(也即key成员变量记录的值)是否一致 * *@return */ privatebooleanisDateEquals(StringnewDateStr){ StringoldDateStr=key; if(!isBlank(oldDateStr)&&oldDateStr.equals(newDateStr)){ returntrue; } returnfalse; } /** *如果日期发生变化,重置计数器,也即将key设置为当前日期,并将value重置为0,重置后才能接着累加, */ privatevoidreSet(AtomicIntegeroldValue,AtomicIntegernewValue,StringnewDateStr){ if(valueUpdater.compareAndSet(this,oldValue,newValue)){ System.out.println("线程"+Thread.currentThread().getName()+"发现日期发生变化"); } } /** *获取当前日期字符串 * *@return */ privateStringgetCurrentDateString(){ Datedate=newDate(); StringnewDateStr=newSimpleDateFormat(DATE_PATTERN).format(date); returnnewDateStr; } /** *计数器的值加1。采用CAS保证线程安全性 * *@paramincrement */ privateintadd(intincrement){ returnvalue.addAndGet(increment); } publicstaticbooleanisBlank(CharSequencecs){ intstrLen; if(cs!=null&&(strLen=cs.length())!=0){ for(inti=0;i li=newArrayList (); intsize=10; CountDownLatchlatch1=newCountDownLatch(1); CountDownLatchlatch2=newCountDownLatch(size); for(inti=0;i 总结
以上就是本文关于Java线程安全的计数器简单实现代码示例的内容,希望对大家有所帮助,感兴趣的朋友可以参阅:Java线程安全基础概念解析、详解java各种集合的线程安全 、Java线程安全与非线程安全解析等。有什么问题可以随时留言,欢迎大家一起交流讨论。感谢朋友们对毛票票网站的支持!