首页 > 其他分享 >System.currentTimeMillis()高并发性能优化

System.currentTimeMillis()高并发性能优化

时间:2023-08-13 12:22:25浏览次数:30  
标签:System private currentTimeMillis 并发 static new now

摘要:System.currentTimeMillis()性能问题的研究、测试与优化。

  性能优化使用的测试环境:

jdk版本jdk8

  操作系统:

  • macOS
  • 版本:13.2.1
  • 芯片: Apple M1
  • CPU核数:8核

  System.currentTimeMillis()是Java极其常用的 API,广泛地用来获取时间戳或统计代码执行耗时等,在我们的印象中应该快如闪电。但实际上在高并发的情况下,其性能表现令人大跌眼镜,调用开销明显变高。

    public static void main(String[] args) throws Exception {
        singleThreadTest();
        multiThreadTest();
    }
    public static void singleThreadTest() {
        //测试一百次循环,每次循环调用System.currentTimeMillis()1千万次数
        for (int t = 0; t < 100; t++) {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            //获取一千万次时间
            for (int i = 0; i < 10000000; i++) {
                System.currentTimeMillis();
            }
            stopWatch.stop();
            System.out.println(stopWatch.getTotalTimeMillis());
        }
    }

    public static void multiThreadTest() throws Exception {
        //100个线程各执行一次
        CountDownLatch wait = new CountDownLatch(1);
        int loopNum = 100;
        CountDownLatch threadLatch = new CountDownLatch(loopNum);
        for (int i = 0; i < loopNum; i++) {
            new Thread(() -> {
                try {
                    StopWatch watch = new StopWatch();
                    //先阻塞住所有线程
                    wait.await();
                    watch.start();
                    for (int j = 0; j < 10000; j++) {
                        System.currentTimeMillis();
                    }
                    watch.stop();
                    System.out.println(watch.getTotalTimeNanos());
                } catch (InterruptedException e) {

                } finally {
                    threadLatch.countDown();
                }
            }).start();
        }
        wait.countDown();
        threadLatch.await();
    }

  执行后,控制台打印的部分执行结果如下:

  由此可见,单线程执行System.currentTimeMillis()比多线程并发执行快了太多倍。至于为什么这么慢,感兴趣的童鞋可以去问问度娘,这里给出一个基于定时任务按照毫秒更新缓存时间戳的方案,也就是在内存中维护一个全局缓存,其它线程取时间戳时从内存读取,代价就是牺牲了一些精确度。具体代码如下:

import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @Author Wiener
 * @Date 2023-08-12
 * @Description: 缓存系统时间
 */
public class SystemClock {

    private final int period;
    private final AtomicLong now;

    private static final String THREAD_NAME ="wienerClock";

    private static class InstanceHolder {
        private static final SystemClock INSTANCE = new SystemClock(1);
    }

    private SystemClock(int period) {
        this.period = period;
        this.now = new AtomicLong(System.currentTimeMillis());
        scheduleClockUpdating();
    }

    private static SystemClock instance() {
        return InstanceHolder.INSTANCE;
    }

    /**
     * 供消费者调用,以替换原来的System.currentTimeMillis()
     */
    public static long now() {
        return instance().now.get();
    }
    private void scheduleClockUpdating() {
        ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1, r -> {
            Thread thread = new Thread(r, THREAD_NAME);
            thread.setDaemon(true);
            return thread;
        });
        // 每秒获取一次系统时间,并赋值给 AtomicLong now
        scheduler.scheduleAtFixedRate(() -> now.set(System.currentTimeMillis()), period, period, TimeUnit.MILLISECONDS);
    }

}

  在并发量大的情况下,使用SystemClock.now()输出当前时间,有一定精度损失,但是提高了系统时间获取效率。

  温馨提示,在System.currentTimeMillis()的效率没有影响程序整体吞吐量时,没有必要做这种优化,这只是为高并发情况准备的。

标签:System,private,currentTimeMillis,并发,static,new,now
From: https://www.cnblogs.com/east7/p/17626389.html

相关文章

  • C#多线程环境下调用 HttpWebRequest 并发连接限制
    .net的HttpWebRequest或者 WebClient 在多线程情况下存在并发连接限制,这个限制在桌面操作系统如windowsxp,windows7下默认是2,在服务器操作系统上默认为10.如果不修改这个并发连接限制,那么客户端同时可以建立的http连接数就只有2个或10个。对于一些诸如浏览器或网络......
  • Android系统启动-SystemServer上篇-1
    相关文件:/frameworks/base/core/java/com/android/internal/os/-ZygoteInit.java-RuntimeInit.java-Zygote.java/frameworks/base/services/java/com/android/server/-SystemServer.java/frameworks/base/core/jni/-com_android_internal_os_Zygote.cp......
  • SystemExit异常 sys.exit()​​函数
    这个错误是SystemExit,它是Python中的一个异常类。当调用sys.exit()函数时,会引发SystemExit异常,这个函数用于退出程序。在你的代码中,sys.exit(0)被调用,参数0表示正常退出程序。在这种情况下,fun_read()函数中的某个条件被满足,导致程序调用了sys.exit(0)来退出。这可能是为了在某些情......
  • 并发并行;同步异步;阻塞非阻塞
    并发/并行;同步/异步;阻塞/非阻塞并发/并行#并行同一时刻,执行多个任务的能力,并行必须是多cpu支持#并发同一时间段内,执行多个任务的能力,所有操作系统都支持并发,单核cpu也可以并发#串行多个任务依次进行,每个任务必须等待上一个任务完成才能开始#扯出去1.python开启多......
  • system.getProperty是一个用于获取系统属性的方法
    system.getProperty是一个用于获取系统属性的方法。系统属性是指与特定运行环境相关的参数和配置信息,通过该方法可以获取这些信息并对程序进行适当的调整和优化。1.什么是系统属性?系统属性是通过系统的配置文件或命令行参数来设置的一些参数和配置信息。腻子粉网站可以影响程序......
  • Debug Assertion Failed! Program: C:\Windows\SYSTEM32\mfc140ud.dll
    新建C++ MFC项目多文本对话框的模板,运行出错。解决办法:这是由于DockControlBar(&m_wndToolBar);引起的异常。在头文件MainFrm.h中重新定义  CMFCToolBar m_wndToolBar; 类型DockControlBar(&m_wndToolBar)改为DockPane(&m_wndToolBar);再次运行就不会出错了。......
  • CI+JUnit5并发单测机制创新实践
    一.现状·问题针对现如今高并发场景的业务系统,“并发问题”终归是必不可少的一类(占比接近10%),每次出现问题和事故后,需要耗费大量人力成本排查分析并修复。那如果能在事前尽可能避免岂不是很香?二.分析原因当前并发测试多数依赖测试人员进行脚本测试,同时还依赖了研发和产品识......
  • HarmonyOS/OpenHarmony应用开发-ArkTSAPI系统能力SystemCapability列表
    SysCap,全称SystemCapability,即系统能力,指操作系统中每一个相对独立的特性。开发者使用某个接口进行开发前,建议先阅读系统能力使用说明,了解Syscap的定义和使用指导。说明当前列表枚举出3.1Beta版本中支持的系统能力。开发者可以在SDK中通过phone.json文件查询。SystemCapability.Ar......
  • 文盘Rust -- Mutex解决并发写文件乱序问题
    在实际开发过程中,我们可能会遇到并发写文件的场景,如果处理不当很可能出现文件内容乱序问题。下面我们通过一个示例程序描述这一过程并给出解决该问题的方法。usestd::{fs::{self,File,OpenOptions},io::{Write},sync::Arc,time::{SystemTime,UNIX_EPOCH}......
  • 并发工具类Phaser
    前言在面试这一篇我们介绍过CountDownLatch和CyclicBarrier,它们都是jdk1.5提供的多线程并发控制类,内部都是用AQS这个同步框架实现。在我们的实际项目中,有很多场景是需要从数据库查询一批数据,多线池执行某些操作,并且要统计结果,我们对这个过程做了一些封装,由于要统计结果,所以需要......