高並發場景下System.currentTimeMillis()的性能優化
阿新 • • 發佈:2018-06-18
rri 1毫秒 明顯 ram gpo IV 結果 如果 system
一、前言
System.currentTimeMillis()的調用比new一個普通對象要耗時的多(具體耗時高出多少我也不知道,不過聽說在100倍左右),然而該方法又是一個常用方法,
有時不得不使用,比如生成wokerId、打印日誌什麽的,在高並發情形下肯定存在性能問題的,但怎麽做才好呢? System.currentTimeMillis()之所以慢是因為
去跟系統打了一次交道。那什麽快?內存!如果該方法從內存直接取數,那不就美滋滋了。
二、代碼實現
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了。
測試
寫了一個簡單的測試代碼:
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毫秒
看著結果效率提升還是挺明顯的。
高並發場景下System.currentTimeMillis()的性能優化