場景:日志需要統計每天數據上傳的次數和上傳的數據量。
如果是單線程可以使用簡單的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!!