System.currentTimeMillis()的調用比new一個普通對象要耗時的多(具體耗時高出多少我也不知道,不過據說在100倍左右),然而該方法又是一個經常使用方法,有時不得不使用,好比生成wokerId、打印日誌什麼的,在高併發情形下確定存在性能問題的,但怎麼作纔好呢? System.currentTimeMillis()之因此慢是由於去跟系統打了一次交道。那什麼快?內存!若是該方法從內存直接取數,那不就美滋滋了。java
package com.nyvi.support.util; import java.sql.Timestamp; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; /** * <p> * 高併發場景下System.currentTimeMillis()的性能問題的優化 * </p> * @author czk */ public class SystemClock { private final long period; private final AtomicLong now; private SystemClock(long period) { this.period = period; this.now = new AtomicLong(System.currentTimeMillis()); scheduleClockUpdating(); } private static SystemClock instance() { return InstanceHolder.INSTANCE; } public static long now() { return instance().currentTimeMillis(); } public static String nowDate() { return new Timestamp(instance().currentTimeMillis()).toString(); } private void scheduleClockUpdating() { ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1, new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r, "System Clock"); thread.setDaemon(true); return thread; } }); scheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() { now.set(System.currentTimeMillis()); } }, period, period, TimeUnit.MILLISECONDS); } private long currentTimeMillis() { return now.get(); } private static class InstanceHolder { public static final SystemClock INSTANCE = new SystemClock(1); } }
用的時候直接調用SystemClock.now();就ok了。sql
寫了一個簡單的測試代碼:併發
public static void main(String[] args) { long start = System.currentTimeMillis(); for (long i = 0; i < Integer.MAX_VALUE; i++) { SystemClock.now(); } long end = System.currentTimeMillis(); System.out.println("SystemClock Time:" + (end - start) + "毫秒"); long start2 = System.currentTimeMillis(); for (long i = 0; i < Integer.MAX_VALUE; i++) { System.currentTimeMillis(); } long end2 = System.currentTimeMillis(); System.out.println("currentTimeMillis Time:" + (end2 - start2) + "毫秒"); }
輸出結果是:
SystemClock Time:1787毫秒
currentTimeMillis Time:33851毫秒
看着結果效率提高仍是挺明顯的。ide