一、前言
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毫秒 看着结果效率提升还是挺明显的。 所有的进步都是不稳定, 一个问题解决了又不得不面对一个新的问题。
转载自:https://www.cnblogs.com/nyvi/p/8837012.html