解决高并发下System.currentTimeMillis卡顿
解决高并发下System.currentTimeMillis卡顿
写工具类SystemClock
package com.baidu.utils; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; public class SystemClock { private final int period; private final AtomicLong now; private static class InstanceHolder { private static final SystemClock INSTANCE = new SystemClock(1); } //定时任务设置1毫秒 private SystemClock(int period) { this.period = period; this.now = new AtomicLong(System.currentTimeMillis()); scheduleClockUpdating(); } private static SystemClock instance() { return InstanceHolder.INSTANCE; } private void scheduleClockUpdating() { //周期执行线程池 ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> { Thread thread = new Thread(runnable, "System Clock"); //守护线程 thread.setDaemon(true); return thread; }); //任务,开始时间,间隔时间=周期执行,时间单位 scheduler.scheduleAtFixedRate(() -> now.set(System.currentTimeMillis()), 0, period, TimeUnit.MILLISECONDS); } private long currentTimeMillis() { return now.get(); } /** * 用来替换原来的System.currentTimeMillis() */ public static long now() { return instance().currentTimeMillis(); } }
测试:
package com.baidu.Test; import com.baidu.utils.SystemClock; public class SystemClockTest { public static void main(String[] args) { int times=Integer.MAX_VALUE; System.out.println("times = " + times); //1 千万次调用,耗时差不多。 // times = 11240000; long start = System.currentTimeMillis(); for (long i = 0; i < times; i++) { SystemClock.now(); } long end = System.currentTimeMillis(); System.out.println("SystemClock Time:" + (end - start) + "毫秒"); long start2 = System.currentTimeMillis(); for (long i = 0; i < times; i++) { System.currentTimeMillis(); } long end2 = System.currentTimeMillis(); System.out.println("SystemCurrentTimeMillis Time:" + (end2 - start2) + "毫秒"); } }
输出结果:
times = 2147483647
SystemClock Time:1102毫秒
SystemCurrentTimeMillis Time:13304毫秒
结论:在调用超过1千万次的高并发场景,不要再直接使用 System.currentTimeMillis() ,而是使用定时器去维护一个 AtomicLong 作为系统时钟,如此可以支持更高的并发量。