摘要: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.currentTimeMillis()高并发性能优化的更多相关文章

  1. 用Netty开发中间件:高并发性能优化

    用Netty开发中间件:高并发性能优化 最近在写一个后台中间件的原型,主要是做消息的分发和透传.因为要用Java实现,所以网络通信框架的第一选择当然就是Netty了,使用的是Netty 4版本.Net ...

  2. 用Netty开发中间件:高并发性能优化(转)

    用Netty开发中间件:高并发性能优化 最近在写一个后台中间件的原型,主要是做消息的分发和透传.因为要用Java实现,所以网络通信框架的第一选择当然就是Netty了,使用的是Netty 4版本.Net ...

  3. GNU Linux高并发性能优化方案

    /*********************************************************** * Author : Samson * Date : 07/14/2015 * ...

  4. SpringCloud高并发性能优化

    1. SpringCloud高并发性能优化 1.1. 前言 当系统的用户量上来,每秒QPS上千后,可能就会导致系统的各种卡顿,超时等情况,这时优化操作不可避免 1.2. 优化步骤 第一步:优化大SQL ...

  5. 高并发&性能优化(二)------系统监控工具使用

    上一篇主要从总体介绍了高并发&性能优化的相关思路和方法,本篇主要介绍系统监控工具. [CPU查看工具] ------top命令(性能) 进入top命令后,按1即可看到每核CPU的运行指标与详细 ...

  6. Java 架构师+高并发+性能优化+Spring boot大型分布式项目实战

    视频课程内容包含: 高级 Java 架构师包含:Spring boot.Spring cloud.Dubbo.Redis.ActiveMQ.Nginx.Mycat.Spring.MongoDB.Zer ...

  7. 高并发&性能优化(一)------总体介绍

    [开篇词] 本文主要通过一些经典的高并发场景,以及一些基本的运维工具来讲述一些关于高并发以及性能优化相关的内容,主要包括性能瓶颈的定位,性能调优的思路和技巧等. [性能的衡量指标] ?什么是性能 性能 ...

  8. Java生鲜电商平台-SpringCloud微服务架构高并发参数优化实战

    Java生鲜电商平台-SpringCloud微服务架构高并发参数优化实战 一.写在前面 在Java生鲜电商平台平台中相信不少朋友都在自己公司使用Spring Cloud框架来构建微服务架构,毕竟现在这 ...

  9. 百万并发中间件系统的内核设计看Java并发性能优化

    “ 这篇文章,给大家聊聊一个百万级并发的中间件系统的内核代码里的锁性能优化. 很多同学都对Java并发编程很感兴趣,学习了很多相关的技术和知识.比如volatile.Atomic.synchroniz ...

  10. Java架构师/高并发/高可用/高扩展/性能优化/框架源码分析实战

    https://ke.qq.com/course/401944?taid=3389721334391320

随机推荐

  1. DeepSeek 官方推出的提示词库,AI内容生成的精准导航仪!

    前言 在当今数字化时代,人工智能(AI)正以前所未有的速度改变着我们的生活方式和工作模式.从简单的数据处理到复杂的创意生成,AI技术正逐渐渗透到各个领域,成为推动社会进步的重要力量.然而,如何高效地利 ...

  2. 基于近红外与可见光双目摄像头的人脸识别与活体检测,文末附Demo

    基于近红外与可见光双目摄像头的活体人脸检测原理 人脸活体检测(Face Anti-Spoofing)是人脸识别系统中的重要一环,它负责验证捕捉到的人脸是否为真实活体,以抵御各种伪造攻击,如彩色纸张打印 ...

  3. LaTeX使用记录

    安装与使用 曾在Windows10下装过MikTeX,并配合vscode插件LaTeX Workshop使用过一段时间:这次转到wsl2中,并使用texlive,所以插件的配置json需要小修改 参考 ...

  4. 启动本地node服务器报错: Access denied for user ‘root‘@‘localhost‘ (using password: YES)

    背景:今天启动node服务时直接报错,顿时一激灵,之前(几个月前哈哈)明明好好的.主要问题就是在连接数据库上,我登上mysql瞅瞅有没有问题,当要输入密码时,emmm, 很好, 忘记root密码了,于 ...

  5. Visio绘制时间轴安排图的方法

      本文介绍基于Visio软件绘制时间轴.日程安排图.时间进度图等的方法.   在很多学习.工作场合中,我们往往需要绘制如下所示的一些带有具体时间进度的日程安排.工作流程.项目进展等可视化图表.    ...

  6. JMeter 通过 BeanShell 脚本处理入参和回参

    入参:可以通过该方式动态生成入参参数,如时间参数,随机参数等. 操作:右键 HTTP Request - Add - Pre Processor - BeanShell PreProcessor im ...

  7. 动态规划--最长公共子序列( LCS 问题)

    博客地址:https://www.cnblogs.com/zylyehuo/ # -*- coding: utf-8 -*- # 最长公共子序列的长度 def lcs_length(x, y): m ...

  8. 【数据库】Java实体类的属性类型与数据库表字段类型对应表

    JDBC类型与Java类型 JDBC类型 Java Object类型 CHAR java.lang.String VARCHAR java.lang.String LONGVARCHAR java.l ...

  9. 附043.KubeEdge边缘云部署实施方案

    目录 KubeEdge介绍 KubeEdge概述 KubeEdge优势 KubeEdge架构 KubeEdge部署 部署依赖 部署规划 主机名配置 变量准备 互信配置 环境预配置 安装keadm 设置 ...

  10. Asp.net mvc基础(十五)EF原理及SQL监控

    EF会自动把Where().OrderBy().Select()等这些编译成"表达式树",然后回把表达式树翻译成SQL语句,因此不是"把数据都取到内存中,然后使用集合的方 ...