为获得更好的阅读体验,请访问原文:传送门

前言: 最近公司来了个大佬,从他那里学到不少东西,其中一个就是计时

的新姿势「StopWatch」,赶紧来一起了解了解吧!

一、最简单的计时


在我们的程序中不免需要对某一个运算或者方法进行计时,以便我们来观察该运算或方法是否符合我们的预期,所以在我们刚开始接触 Java 的时候都能写出类似下面这样的代码来计时:

public static void main(String[] args) {
Long startTime = System.currentTimeMillis(); doSomeThing(); Long endTime = System.currentTimeMillis();
Long elapsedTime = (endTime - startTime) / 1000;
System.out.println("总共耗时:" + elapsedTime + "s");
}
// 用于模拟一些操作
private static void doSomeThing() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

事实上这样也并没有什么问题,并且也能够运行的很好,但是有一点不太好的就是,自己关注了太多输出的信息,下面我们来认识一种更优雅的一种计时方式;

二、StopWatch 类


想要使用它,首先你需要在你的 Maven 中引入 Spring 核心包,当然 Spring MVC 和 Spring Boot 都已经自动引入了该包:

<!-- spring核心包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>

现在我们计时的姿势或许就会变成以下这样:

public static void main(String[] args) {
StopWatch clock = new StopWatch(); clock.start("开始任务一");
doSomeThing();
clock.stop(); clock.start("开始任务二");
doSomeThing();
clock.stop(); System.out.println(clock.prettyPrint());
} // 用于模拟一些操作
private static void doSomeThing() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

在最后我们使用 StopWatch 类自带的 prettyPrint() 方法类格式化我们的输出,运行程序你会发现你的程序输出了这样的东西:

StopWatch '': running time (millis) = 2009
-----------------------------------------
ms % Task name
-----------------------------------------
01005 050% 开始任务一
01004 050% 开始任务二

不仅有总用时,还有每个任务分别的占用时间和占用时间的百分比,这或许就会比我们自己输出要优雅那么一些;

StopWatch 类是怎么实现的呢?

当你戳开 StopWatch 的源码,你会在总共不到 200 行的代码里看到熟悉的东西:

    public void start(String taskName) throws IllegalStateException {
if (this.currentTaskName != null) {
throw new IllegalStateException("Can't start StopWatch: it's already running");
} else {
this.currentTaskName = taskName;
this.startTimeMillis = System.currentTimeMillis();
}
} public void stop() throws IllegalStateException {
if (this.currentTaskName == null) {
throw new IllegalStateException("Can't stop StopWatch: it's not running");
} else {
long lastTime = System.currentTimeMillis() - this.startTimeMillis;
this.totalTimeMillis += lastTime;
this.lastTaskInfo = new StopWatch.TaskInfo(this.currentTaskName, lastTime);
if (this.keepTaskList) {
this.taskList.add(this.lastTaskInfo);
} ++this.taskCount;
this.currentTaskName = null;
}
}

你会发现该类使用 LinkedList 实现了一个叫做 taskList 的队列,然后每一次开始同样也是使用 System.currentTimeMillis() 方法来获取时间,每次除了计算耗时也会构建一个描述当前任务的 TaskInfo 对象,并把它放入 taskList 队列中。

当执行 prettyPrint() 方法的时候,就从 taskList 队列中依次取出任务,然后做些格式化的操作:

    public String shortSummary() {
return "StopWatch '" + this.getId() + "': running time (millis) = " + this.getTotalTimeMillis();
} public String prettyPrint() {
StringBuilder sb = new StringBuilder(this.shortSummary());
sb.append('\n');
if (!this.keepTaskList) {
sb.append("No task info kept");
} else {
sb.append("-----------------------------------------\n");
sb.append("ms % Task name\n");
sb.append("-----------------------------------------\n");
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMinimumIntegerDigits(5);
nf.setGroupingUsed(false);
NumberFormat pf = NumberFormat.getPercentInstance();
pf.setMinimumIntegerDigits(3);
pf.setGroupingUsed(false);
StopWatch.TaskInfo[] var4 = this.getTaskInfo();
int var5 = var4.length; for(int var6 = 0; var6 < var5; ++var6) {
StopWatch.TaskInfo task = var4[var6];
sb.append(nf.format(task.getTimeMillis())).append(" ");
sb.append(pf.format(task.getTimeSeconds() / this.getTotalTimeSeconds())).append(" ");
sb.append(task.getTaskName()).append("\n");
}
} return sb.toString();
}

摁,新姿势 get √。


按照惯例黏一个尾巴:

欢迎转载,转载请注明出处!

独立域名博客:wmyskxz.com

简书ID:@我没有三颗心脏

github:wmyskxz

欢迎关注公众微信号:wmyskxz

分享自己的学习 & 学习资料 & 生活

想要交流的朋友也可以加qq群:3382693

Java计时新姿势的更多相关文章

  1. Python一键转Jar包,Java调用Python新姿势!

    粉丝朋友们,不知道大家看故事看腻了没(要是没腻可一定留言告诉我^_^),今天这篇文章换换口味,正经的来写写技术文.言归正传,咱们开始吧! 本文结构: 需求背景 进击的Python Java和Pytho ...

  2. Java 8新特性之旅:使用Stream API处理集合

    在这篇“Java 8新特性教程”系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章“遍历.过滤.处理集合及使用Lambda ...

  3. 最通俗易懂的 Java 11 新特性讲解

    大多数开发者还是沉浸在 Java 8 中,而 Java 14 将要在 2020 年 3 月 17 日发布了,而我还在写着 Java 11 的新特性.Java 11 是 Java 8 之后的第一个 LT ...

  4. Java 8新特性-4 方法引用

    对于引用来说我们一般都是用在对象,而对象引用的特点是:不同的引用对象可以操作同一块内容! Java 8的方法引用定义了四种格式: 引用静态方法     ClassName :: staticMetho ...

  5. Java 8新特性终极指南

    目录结构 介绍 Java语言的新特性 2.1 Lambdas表达式与Functional接口 2.2 接口的默认与静态方法 2.3 方法引用 2.4 重复注解 2.5 更好的类型推测机制 2.6 扩展 ...

  6. Spring 4支持的Java 8新特性一览

    有众多新特性和函数库的Java 8发布之后,Spring 4.x已经支持其中的大部分.有些Java 8的新特性对Spring无影响,可以直接使用,但另有些新特性需要Spring的支持.本文将带您浏览S ...

  7. Atitit  java jsp 新的tag技术

    Atitit  java jsp 新的tag技术 1.1.  Tag Files  vs 原生写 SimpleTag 比较麻烦的 JSP 1.x 允许 Web 开发人员创建 Java 组件(称为标记处 ...

  8. java 8 新特性

    最近在IDEA的️驱使下,看了点java8的东西,链接贴一下,,,,, 1.Java 8新特性概述2.Java 8中的 Stream API 详解[3.Java 8新特性终极指南] 简单的使用看完新特 ...

  9. 【转+自己研究】新姿势之Docker Remote API未授权访问漏洞分析和利用

    0x00 概述 最近提交了一些关于 docker remote api 未授权访问导致代码泄露.获取服务器root权限的漏洞,造成的影响都比较严重,比如 新姿势之获取果壳全站代码和多台机器root权限 ...

随机推荐

  1. Zookeeper详解-工作流和leader选举(三)

    一.工作流 一旦ZooKeeper集合启动,它将等待客户端连接.客户端将连接到ZooKeeper集合中的一个节点.它可以是leader或follower节点.一旦客户端被连接,节点将向特定客户端分配会 ...

  2. MyBatis从入门到精通(三):MyBatis XML方式的基本用法之多表查询

    最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. 多表查询 上篇博客中,我们示例的 ...

  3. 浅谈Linq查询

    一.Var关键字 在学习Linq查询之前,我们先来学习var关键字的用法,看看微软官方的定义:从Visual C#3.0开始,在方法范围声明的变量可以具有隐式“类型” var.隐式类型的局部变量是强类 ...

  4. Django中间件加载原理

    假设我们有如下中间件: setting.py文件 MIDDLEWARE = [ 'django.middleware.A', 'django.middleware.B', 'django.middle ...

  5. JAVA开发第一步 - JDK安装与配置

    JDK的安装与环境变量配置是JAVA开发之路的第一步,很多新人在这一步上就卡了很久,浪费了很多时间,甚至有些人就轻易地“从入门到放弃”了.今天我们就来一步步教你如何打倒这第一只拦路虎. 1.JDK下载 ...

  6. nginx实战操作(常用命令及配置)

    1. nginx介绍 2. nginx常用命令 验证配置是否正确: nginx -t 查看Nginx的详细的版本号:nginx -V 查看Nginx的简洁版本号:nginx -v 启动Nginx:st ...

  7. STM32F0_HAL库驱动描述——基于F1的USART串口IT中断实现解析

    从原子F103 HAL库基础串口例程来看HAL程序结构: 从main函数开始,首先是HAL库两个函数的初始化: HAL_Init(): Stm32_Clock_Init(RCC_PLL_MUL9); ...

  8. java学习笔记(基础篇)--java关键字与数据类型

    java关键字与数据类型 Java语言的关键字是程序代码中的特殊字符.包括: . 类和接口的声明--class, extends, implements, interface . 包引入和包声明--i ...

  9. python的ORM技巧记录

    # -*- coding:utf-8 -*- from sqlalchemy import create_engine, Column, Integer, String, ForeignKey, In ...

  10. Python入门基础(9)__面向对象编程_1

    定义一个只包含方法的类 class 类名: def 方法1(self,参数列表): pass def 方法2(self,参数列表): pass 当一个类定义之后,要使用这个类来创键对象.语法如下: 对 ...