System.currentTimeMillis()优化方案
System.currentTimeMillis()在java中是最常用的获取系统时间的方法,它返回的是1970年1月1日0点到现在经过的毫秒数。
针对System.currentTimeMillis()性能不好的原因分析,有一篇很好的文章The slow currentTimeMillis(),它直接从系统级、源码、汇编语言各个层次全方位的分析。
从The slow currentTimeMillis()中我们了解到,执行速度缓慢currentTimeMillis()是由两个因素造成的:
- JVM使用gettimeofday() 而不是clock_gettime()
- gettimeofday() 如果使用HPET时间源,则速度非常慢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong;
public class SystemTimeMilli {
private final int period;
private final AtomicLong now;
private static class InstanceHolder { private static final SystemTimeMilli INSTANCE = new SystemTimeMilli(1); }
private SystemTimeMilli(int period) { this.period = period; this.now = new AtomicLong(System.currentTimeMillis()); scheduleClockUpdating(); }
private static SystemTimeMilli instance() { return InstanceHolder.INSTANCE; }
private void scheduleClockUpdating() { ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable runnable) { Thread thread = new Thread(runnable, "System-Time-Milli"); thread.setDaemon(true); return thread; } }); scheduler.scheduleAtFixedRate(() -> now.set(System.currentTimeMillis()), period, period, TimeUnit.MILLISECONDS); }
private long currentTimeMillis() { return now.get(); }
public static long now() { return instance().currentTimeMillis(); } }
|
参考地址