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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM