场景:日志需要统计每天数据上传的次数和上传的数据量。
如果是单线程可以使用简单的int count = 0;count++,但很多情况都是多线程环境所以就不能单纯的使用count++了!!!
多线程环境采用 java.util.concurrent.atomic 下的AtomicLong类,该类的介绍可看API文档。可以用原子方式更新的 long
值。有关原子变量属性的描述,请参阅 java.util.concurrent.atomic
包规范。AtomicLong
可用在应用程序中(如以原子方式增加的序列号),并且不能用于替换 Long
。但是,此类确实扩展了 Number
,允许那些处理基于数字类的工具和实用工具进行统一访问。每天都要把统计的次数置为0,可以使用定时器,每天零点零分将次数重置为0,该方法不易拓展;另一种方法是使用全局变量时间戳,判断当前日期是不是与时间戳相等,如果是就说明今天的次数累加;如果不是就要把时间戳重置为当天的日期,并把次数重置为0。多线程情况下采用锁加double check方法确保解决并发问题!
1 public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); 2 3 /** 4 * 获得当前日期 5 * <p> 6 * 日期格式yyyy-MM-dd 7 * 8 * @return 9 */ 10 public static String currentDate() { 11 return DATE_FORMAT.format(new Date()); 12 }
1 //上传次数 2 private final AtomicLong count = new AtomicLong(0); 3 4 //上传数据量 5 private final AtomicLong dataSize = new AtomicLong(0); 6 7 //时间戳 8 private String today = DateUtils.currentDate(); 9 10 public void getLog(Integer size){ 11 String systTime = DateUtils.currentDate(); 12 //如果日期不是当天的 13 if(today!=null && !systTime.equals(today)){ 14 synchronized (today) { 15 if(today!=null && !systTime.equals(today)){ 16 today=systTime; 17 count.set(0); 18 dataSize.set(0); 19 } 20 } 21 } 22 count.incrementAndGet(); 23 dataSize.addAndGet(size); 24 if(logger.isInfoEnabled()) { 25 logger.info(String.format("That day receive data the %sth times,total %s data !",count.get(),dataSize.get())); 26 } 27 }
还有很关键的一个问题不要忽略,就是该类是单例的,这样确保所有线程共享同一个count,dataSize只有一个对象!或者将count,dataSize设置成static!!