最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java計(jì)時(shí)器工具StopWatch的具體使用

 更新時(shí)間:2022年04月06日 11:49:19   作者:陳皮的JavaLib  
計(jì)時(shí)器在很多地方都可以用到,本文主要介紹了Java計(jì)時(shí)器工具StopWatch的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

平常,我們想要統(tǒng)計(jì)某一段代碼塊,或某一個(gè)方法的執(zhí)行時(shí)間,最簡(jiǎn)單的是采用如下的方式。

 package com.chenpi;
 ?
 /**
  * @author 陳皮
  * @version 1.0
  * @description
  * @date 2022/4/2
  */
 public class ChenPi {
 ?
   public static void main(String[] args) throws InterruptedException {
     long startTime = System.currentTimeMillis();
     Thread.sleep(1000);
     long endTime = System.currentTimeMillis();
     System.out.println("執(zhí)行耗時(shí)(ms):" + (endTime - startTime));
   }
 ?
 }
 ?
 // 輸出結(jié)果如下
 執(zhí)行耗時(shí)(ms):1011

但如果我們想對(duì)多個(gè)代碼段進(jìn)行計(jì)時(shí),以及每個(gè)階段計(jì)時(shí)的占比等信息,如果還是采用如上的方式就會(huì)充斥比較多的與業(yè)務(wù)無(wú)關(guān)的代碼,不夠簡(jiǎn)潔。

Spring StopWatch

Spring 框架有個(gè)工具類 StopWatch,它可以用來(lái)對(duì)程序中代碼塊,或者方法進(jìn)行計(jì)時(shí),并且支持多階段計(jì)時(shí),以及階段時(shí)間占比等統(tǒng)計(jì),使用起來(lái)代碼比較簡(jiǎn)潔,輕量。

 package com.chenpi;
 ?
 import org.springframework.util.StopWatch;
 ?
 /**
  * @author 陳皮
  * @version 1.0
  * @description
  * @date 2022/4/2
  */
 public class ChenPi {
 ?
   public static void main(String[] args) throws InterruptedException {
     // 聲明一個(gè)計(jì)時(shí)器
     StopWatch stopWatch = new StopWatch("陳皮的計(jì)時(shí)器");
     // 開始計(jì)時(shí)
     stopWatch.start("發(fā)送MQ計(jì)時(shí)");
     Thread.sleep(1000);
     // 結(jié)束計(jì)時(shí)
     stopWatch.stop();
     // 打印統(tǒng)計(jì)
     System.out.println(stopWatch.prettyPrint());
   }
 ?
 }
 ?
 ?
 // 輸出結(jié)果如下
 StopWatch '陳皮的計(jì)時(shí)器': running time = 1005775500 ns
 ---------------------------------------------
 ns         %     Task name
 ---------------------------------------------
 1005775500  100%  發(fā)送MQ計(jì)時(shí)

Spring StopWatch 有以下幾個(gè)常用方法:

  • StopWatch():構(gòu)造一個(gè)計(jì)時(shí)器
  • StopWatch(String id):構(gòu)造一個(gè)指定 id 的計(jì)時(shí)器
  • start():創(chuàng)建一個(gè)名為空字符串的計(jì)時(shí)任務(wù),開始計(jì)時(shí)
  • start(String taskName):創(chuàng)建一個(gè)指定名稱計(jì)時(shí)任務(wù),開始計(jì)時(shí)
  • stop():結(jié)束當(dāng)前任務(wù)的計(jì)時(shí)
  • getTotalTimeNanos():獲取全部任務(wù)的執(zhí)行時(shí)間,單位納秒
  • getTotalTimeMillis():獲取全部任務(wù)的執(zhí)行時(shí)間,單位毫秒
  • shortSummary():獲取簡(jiǎn)單的統(tǒng)計(jì)信息
  • prettyPrint():以友好方式輸出總統(tǒng)計(jì)時(shí)間,以及各個(gè)階段任務(wù)的執(zhí)行時(shí)間
  • setKeepTaskList(boolean keepTaskList):是否在內(nèi)部的列表中存儲(chǔ)每一個(gè)任務(wù)

實(shí)踐例子

當(dāng)程序中有多個(gè)計(jì)時(shí)器時(shí),可通過(guò)構(gòu)造不同 id 的計(jì)時(shí)器來(lái)區(qū)分。以下演示多個(gè)不同計(jì)時(shí)器,統(tǒng)計(jì)不同階段的執(zhí)行時(shí)間。

 package com.chenpi;
 ?
 import org.springframework.util.StopWatch;
 ?
 /**
  * @author 陳皮
  * @version 1.0
  * @description
  * @date 2022/4/2
  */
 public class ChenPi {
 ?
   public static void main(String[] args) throws InterruptedException {
     m1();
     m2();
   }
 ?
   private static void m1() throws InterruptedException {
 ?
     // 聲明一個(gè)計(jì)時(shí)器
     StopWatch stopWatch = new StopWatch("m1計(jì)時(shí)器");
 ?
     stopWatch.start("查詢數(shù)據(jù)庫(kù)");
     Thread.sleep(1000);
     stopWatch.stop();
 ?
     stopWatch.start("邏輯計(jì)算");
     Thread.sleep(500);
     stopWatch.stop();
 ?
     System.out.println(stopWatch.prettyPrint());
   }
 ?
   private static void m2() throws InterruptedException {
 ?
     // 聲明一個(gè)計(jì)時(shí)器
     StopWatch stopWatch = new StopWatch("m2計(jì)時(shí)器");
 ?
     stopWatch.start("遠(yuǎn)程調(diào)用");
     Thread.sleep(800);
     stopWatch.stop();
 ?
     stopWatch.start("發(fā)送MQ");
     Thread.sleep(200);
     stopWatch.stop();
 ?
     System.out.println(stopWatch.prettyPrint());
   }
 }
 ?
 // 輸出結(jié)果如下
 StopWatch 'm1計(jì)時(shí)器': running time = 1516953200 ns
 ---------------------------------------------
 ns         %     Task name
 ---------------------------------------------
 1008091000  066%  查詢數(shù)據(jù)庫(kù)
 508862200  034%  邏輯計(jì)算
 ?
 StopWatch 'm2計(jì)時(shí)器': running time = 1013080000 ns
 ---------------------------------------------
 ns         %     Task name
 ---------------------------------------------
 809345900  080%  遠(yuǎn)程調(diào)用
 203734100  020%  發(fā)生MQ

源碼分析

其實(shí) StopWatch 底層實(shí)現(xiàn)很簡(jiǎn)單,對(duì)于每一個(gè)任務(wù),在任務(wù)開始和結(jié)束時(shí)刻調(diào)用System.*nanoTime*()方法獲取服務(wù)器當(dāng)前的時(shí)間,然后計(jì)算每一個(gè)任務(wù)的執(zhí)行時(shí)間,存儲(chǔ)在內(nèi)部。內(nèi)部使用一個(gè)列表存儲(chǔ)不同任務(wù)階段的執(zhí)行時(shí)間,最后打印輸出。

package org.springframework.util;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.lang.Nullable;

public class StopWatch {

	// 計(jì)時(shí)器id
	private final String id;

    // 是否將任務(wù)存儲(chǔ)到任務(wù)列表中
	private boolean keepTaskList = true;

    // 存儲(chǔ)全部任務(wù)的列表
	private final List<TaskInfo> taskList = new ArrayList<>(1);

	// 當(dāng)前任務(wù)開始時(shí)間
	private long startTimeNanos;

	// 當(dāng)前任務(wù)名稱
	@Nullable
	private String currentTaskName;

    // 最后一個(gè)任務(wù)
	@Nullable
	private TaskInfo lastTaskInfo;

    // 總?cè)蝿?wù)數(shù)
	private int taskCount;

	// 總的執(zhí)行時(shí)間
	private long totalTimeNanos;

    // 構(gòu)造一個(gè)id為空字符串的計(jì)時(shí)器
	public StopWatch() {
		this("");
	}

    // 構(gòu)造一個(gè)指定id的計(jì)時(shí)器
	public StopWatch(String id) {
		this.id = id;
	}

    // 獲取計(jì)時(shí)器id
	public String getId() {
		return this.id;
	}

	public void setKeepTaskList(boolean keepTaskList) {
		this.keepTaskList = keepTaskList;
	}

    // 開始計(jì)時(shí)
	public void start() throws IllegalStateException {
		start("");
	}

    // 開始一個(gè)指定任務(wù)名稱的計(jì)時(shí)
	public void start(String taskName) throws IllegalStateException {
		if (this.currentTaskName != null) {
			throw new IllegalStateException("Can't start StopWatch: it's already running");
		}
		this.currentTaskName = taskName;
		this.startTimeNanos = System.nanoTime();
	}

	// 停止任務(wù)計(jì)時(shí)
	public void stop() throws IllegalStateException {
		if (this.currentTaskName == null) {
			throw new IllegalStateException("Can't stop StopWatch: it's not running");
		}
		long lastTime = System.nanoTime() - this.startTimeNanos;
		this.totalTimeNanos += lastTime;
		this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);
		if (this.keepTaskList) {
			this.taskList.add(this.lastTaskInfo);
		}
		++this.taskCount;
		this.currentTaskName = null;
	}

	public boolean isRunning() {
		return (this.currentTaskName != null);
	}

	@Nullable
	public String currentTaskName() {
		return this.currentTaskName;
	}

	public long getLastTaskTimeNanos() throws IllegalStateException {
		if (this.lastTaskInfo == null) {
			throw new IllegalStateException("No tasks run: can't get last task interval");
		}
		return this.lastTaskInfo.getTimeNanos();
	}

	public long getLastTaskTimeMillis() throws IllegalStateException {
		if (this.lastTaskInfo == null) {
			throw new IllegalStateException("No tasks run: can't get last task interval");
		}
		return this.lastTaskInfo.getTimeMillis();
	}

	public String getLastTaskName() throws IllegalStateException {
		if (this.lastTaskInfo == null) {
			throw new IllegalStateException("No tasks run: can't get last task name");
		}
		return this.lastTaskInfo.getTaskName();
	}

	public TaskInfo getLastTaskInfo() throws IllegalStateException {
		if (this.lastTaskInfo == null) {
			throw new IllegalStateException("No tasks run: can't get last task info");
		}
		return this.lastTaskInfo;
	}

	public long getTotalTimeNanos() {
		return this.totalTimeNanos;
	}

	public long getTotalTimeMillis() {
		return nanosToMillis(this.totalTimeNanos);
	}

	public double getTotalTimeSeconds() {
		return nanosToSeconds(this.totalTimeNanos);
	}

	public int getTaskCount() {
		return this.taskCount;
	}

	public TaskInfo[] getTaskInfo() {
		if (!this.keepTaskList) {
			throw new UnsupportedOperationException("Task info is not being kept!");
		}
		return this.taskList.toArray(new TaskInfo[0]);
	}

	public String shortSummary() {
		return "StopWatch '" + getId() + "': running time = " + getTotalTimeNanos() + " ns";
	}

	public String prettyPrint() {
		StringBuilder sb = new StringBuilder(shortSummary());
		sb.append('\n');
		if (!this.keepTaskList) {
			sb.append("No task info kept");
		}
		else {
			sb.append("---------------------------------------------\n");
			sb.append("ns         %     Task name\n");
			sb.append("---------------------------------------------\n");
			NumberFormat nf = NumberFormat.getNumberInstance();
			nf.setMinimumIntegerDigits(9);
			nf.setGroupingUsed(false);
			NumberFormat pf = NumberFormat.getPercentInstance();
			pf.setMinimumIntegerDigits(3);
			pf.setGroupingUsed(false);
			for (TaskInfo task : getTaskInfo()) {
				sb.append(nf.format(task.getTimeNanos())).append("  ");
				sb.append(pf.format((double) task.getTimeNanos() / getTotalTimeNanos())).append("  ");
				sb.append(task.getTaskName()).append('\n');
			}
		}
		return sb.toString();
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder(shortSummary());
		if (this.keepTaskList) {
			for (TaskInfo task : getTaskInfo()) {
				sb.append("; [").append(task.getTaskName()).append("] took ").append(task.getTimeNanos()).append(" ns");
				long percent = Math.round(100.0 * task.getTimeNanos() / getTotalTimeNanos());
				sb.append(" = ").append(percent).append('%');
			}
		}
		else {
			sb.append("; no task info kept");
		}
		return sb.toString();
	}


	private static long nanosToMillis(long duration) {
		return TimeUnit.NANOSECONDS.toMillis(duration);
	}

	private static double nanosToSeconds(long duration) {
		return duration / 1_000_000_000.0;
	}

    // 任務(wù)實(shí)體
	public static final class TaskInfo {

        // 任務(wù)名稱
		private final String taskName;

        // 任務(wù)執(zhí)行時(shí)間
		private final long timeNanos;

		TaskInfo(String taskName, long timeNanos) {
			this.taskName = taskName;
			this.timeNanos = timeNanos;
		}

		public String getTaskName() {
			return this.taskName;
		}

		public long getTimeNanos() {
			return this.timeNanos;
		}

		public long getTimeMillis() {
			return nanosToMillis(this.timeNanos);
		}

		public double getTimeSeconds() {
			return nanosToSeconds(this.timeNanos);
		}

	}

}
復(fù)制代碼

StopWatch 使用起來(lái)簡(jiǎn)潔,支持多任務(wù)階段統(tǒng)計(jì),統(tǒng)計(jì)多任務(wù)時(shí)間占比等,統(tǒng)計(jì)結(jié)果直觀。但是它也有不好的地方,就是一個(gè) StopWatch 實(shí)例只能同時(shí) start 一個(gè) task,只能等這個(gè) task 進(jìn)行 stop 之后,才能繼續(xù) start 另一個(gè) task。注意,StopWatch 實(shí)例不是線程安全的,也沒(méi)必要進(jìn)行同步處理。

lang3 StopWatch

Apache commons lang3 包下也有一個(gè)用于計(jì)時(shí)工具類 StopWatch。它還有暫停計(jì)時(shí),恢復(fù)計(jì)時(shí),設(shè)置分割點(diǎn)等功能。

&nbsp;org.apache.commons:commons-lang3:3.12.0
復(fù)制代碼

它主要有以下幾個(gè)常用方法:

  • create():實(shí)例化一個(gè)計(jì)時(shí)器
  • createStarted():實(shí)例化一個(gè)計(jì)時(shí)器,并開始計(jì)時(shí)
  • StopWatch(final String message):實(shí)例化一個(gè)帶有標(biāo)識(shí)符的計(jì)時(shí)器
  • start():開始計(jì)時(shí)
  • split():設(shè)置分割點(diǎn)
  • getSplitTime():統(tǒng)計(jì)從 start 開始最后一個(gè)分割點(diǎn)的用時(shí)
  • reset():重置計(jì)時(shí)
  • suspend():暫停計(jì)時(shí)
  • resume():恢復(fù)計(jì)時(shí)
  • stop():停止計(jì)時(shí)
  • getTime():統(tǒng)計(jì)從 start 到當(dāng)前時(shí)刻的同時(shí)
 package com.chenpi;
 ?
 import org.apache.commons.lang3.time.StopWatch;
 ?
 /**
  * @author 陳皮
  * @version 1.0
  * @description
  * @date 2022/4/2
  */
 public class ChenPi {
 ?
   public static void main(String[] args) throws InterruptedException {
 ?
     // 聲明一個(gè)計(jì)時(shí)器
     StopWatch stopWatch = new StopWatch("m1計(jì)時(shí)器");
 ?
     stopWatch.start();
     Thread.sleep(1000);
     System.out.println("start開始到現(xiàn)在的時(shí)間:" + stopWatch.getTime());
 ?
     stopWatch.split();
     Thread.sleep(500);
     System.out.println("start開始到最后一個(gè)split的時(shí)間:" + stopWatch.getSplitTime());
 ?
     stopWatch.split();
     Thread.sleep(500);
     System.out.println("start開始到最后一個(gè)split的時(shí)間:" + stopWatch.getSplitTime());
 ?
     // 重置計(jì)時(shí)
     stopWatch.reset();
     Thread.sleep(2000);
     stopWatch.start();
     Thread.sleep(1000);
     System.out.println("start開始到現(xiàn)在的時(shí)間:" + stopWatch.getTime());
 ?
     // 暫停計(jì)時(shí)
     stopWatch.suspend();
     Thread.sleep(3000);
     // 恢復(fù)計(jì)時(shí)
     stopWatch.resume();
 ?
     Thread.sleep(1000);
 ?
     // 結(jié)束計(jì)時(shí)
     stopWatch.stop();
 ?
     Thread.sleep(1000);
 ?
     System.out.println("start開始到stop結(jié)束的時(shí)間:" + stopWatch.getTime());
 ?
     System.out.println(stopWatch);
   }
 }
 ?
 // 輸出結(jié)果如下
 start開始到現(xiàn)在的時(shí)間:1000
 start開始到最后一個(gè)split的時(shí)間:1001
 start開始到最后一個(gè)split的時(shí)間:1510
 start開始到現(xiàn)在的時(shí)間:1004
 start開始到stop結(jié)束的時(shí)間:2015
 m1計(jì)時(shí)器 00:00:02.015

總結(jié)

  • 如果是簡(jiǎn)單的計(jì)算執(zhí)行計(jì)時(shí),可以使用 JDK 自帶的類獲取系統(tǒng)時(shí)間進(jìn)行計(jì)時(shí)。
  • 如果需要多階段計(jì)時(shí),并且需要統(tǒng)計(jì)每個(gè)階段的執(zhí)行時(shí)間占比等信息,可以使用 StopWatch 工具類。
  • 推薦使用 Spring StopWatch,因?yàn)楸旧砦覀冺?xiàng)目使用 Spring 框架比較多,這樣就自帶了 StopWatch。

到此這篇關(guān)于Java計(jì)時(shí)器工具StopWatch的具體使用的文章就介紹到這了,更多相關(guān)Java計(jì)時(shí)器工具StopWatch內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Netty分布式ByteBuf使用page級(jí)別的內(nèi)存分配解析

    Netty分布式ByteBuf使用page級(jí)別的內(nèi)存分配解析

    這篇文章主要介紹了Netty分布式ByteBuf使用page級(jí)別的內(nèi)存分配解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • SpringBoot項(xiàng)目鑒權(quán)的4種方式小結(jié)

    SpringBoot項(xiàng)目鑒權(quán)的4種方式小結(jié)

    本文主要介紹了SpringBoot項(xiàng)目鑒權(quán)的4種方式小結(jié),包括傳統(tǒng)AOP、攔截器、參數(shù)解析器和過(guò)濾器,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 一文帶你搞懂Redis分布式鎖

    一文帶你搞懂Redis分布式鎖

    本篇文章主要來(lái)介紹一下如何Redis實(shí)現(xiàn)分布式鎖的演進(jìn)過(guò)程,以及為什么不能直接用Setnx實(shí)現(xiàn)分布式鎖,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2022-09-09
  • JavaCV實(shí)現(xiàn)讀取視頻信息及自動(dòng)截取封面圖詳解

    JavaCV實(shí)現(xiàn)讀取視頻信息及自動(dòng)截取封面圖詳解

    javacv可以幫助我們?cè)趈ava中很方便的使用OpenCV以及FFmpeg相關(guān)的功能接口。本文將利用Javacv實(shí)現(xiàn)在視頻網(wǎng)站中常見的讀取視頻信息和自動(dòng)獲取封面圖的功能,感興趣的可以了解一下
    2022-06-06
  • Spring Boot 文件上傳與下載的示例代碼

    Spring Boot 文件上傳與下載的示例代碼

    這篇文章主要介紹了Spring Boot 文件上傳與下載的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Springmvc和ajax如何實(shí)現(xiàn)前后端交互

    Springmvc和ajax如何實(shí)現(xiàn)前后端交互

    這篇文章主要介紹了Springmvc和ajax如何實(shí)現(xiàn)前后端交互,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 通過(guò)spring boot 設(shè)置tomcat解決 post參數(shù)限制問(wèn)題

    通過(guò)spring boot 設(shè)置tomcat解決 post參數(shù)限制問(wèn)題

    這篇文章主要介紹了通過(guò)spring boot 設(shè)置tomcat解決 post參數(shù)限制問(wèn)題,需要的朋友可以參考下
    2019-05-05
  • Maven配置倉(cāng)庫(kù)、阿里云鏡像、環(huán)境變量(史上最全)

    Maven配置倉(cāng)庫(kù)、阿里云鏡像、環(huán)境變量(史上最全)

    本文主要介紹了Maven配置倉(cāng)庫(kù)、阿里云鏡像、環(huán)境變量,文中通過(guò)圖文示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • SpringBoot混合使用StringRedisTemplate和RedisTemplate的坑及解決

    SpringBoot混合使用StringRedisTemplate和RedisTemplate的坑及解決

    這篇文章主要介紹了SpringBoot混合使用StringRedisTemplate和RedisTemplate的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Springboot actuator應(yīng)用后臺(tái)監(jiān)控實(shí)現(xiàn)

    Springboot actuator應(yīng)用后臺(tái)監(jiān)控實(shí)現(xiàn)

    這篇文章主要介紹了Springboot actuator應(yīng)用后臺(tái)監(jiān)控實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04

最新評(píng)論

遂平县| 广河县| 个旧市| 阿拉善左旗| 洮南市| 肇东市| 宜阳县| 静乐县| 鹤岗市| 宣恩县| 龙门县| 来宾市| 夏邑县| 三门县| 股票| 射洪县| 绥中县| 崇文区| 五台县| 鄂尔多斯市| 宁国市| 军事| 沈阳市| 蓝山县| 泊头市| 兴义市| 邹城市| 高邑县| 吉木萨尔县| 分宜县| 延安市| 寿宁县| 上思县| 桐城市| 宜阳县| 乌兰浩特市| 道孚县| 乳源| 柳州市| 英吉沙县| 城口县|