解決高並發下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 作為系統時鍾,如此可以支持更高的並發量。