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;ili=newArrayList();
intsize=10;
CountDownLatchlatch1=newCountDownLatch(1);
CountDownLatchlatch2=newCountDownLatch(size);
for(inti=0;i
总结
以上就是本文关于Java线程安全的计数器简单实现代码示例的内容,希望对大家有所帮助,感兴趣的朋友可以参阅:Java线程安全基础概念解析、详解java各种集合的线程安全 、Java线程安全与非线程安全解析等。有什么问题可以随时留言,欢迎大家一起交流讨论。感谢朋友们对毛票票网站的支持!