我们经常需要统计一个方法的耗时。通常,我们会这样做://休眠100ms,模拟任务耗时Thread.sleep(100L);长端=System.currentTimeMillis();System.out.println("耗时:"+(end-start));//Outputtime-consumed:104}}这样做虽然简单明了,但是当我们需要按段统计耗时时,一不小心就会找不到开始时间。而且无法总结结果,无法直观看出每一步的耗时。有一个简单的小工具可以帮助我们使耗时的统计方法变得非常简单。名字是秒表。常见的库,如Spring、ApacheCommons和GoogleGuava都有这个工具。功能和实现是相似的。推荐使用Spring中的,可以更方便统计耗时的汇总结果。尝试用StopWatch替换耗时的代码://开始计时stopWatch.start();//休眠100ms,模拟任务耗时Thread.sleep(100L);//结束计时stopWatch.stop();//打印统计结果System.out.println(stopWatch.prettyPrint());}}输出结果为:StopWatch'':运行时间(millis)=104----------------------------------------ms%任务名称------------------------------------------00104100%只统计了一项任务的耗时,无法体现StopWatch的优势。下面统计一次多个任务的耗时:publicclassCopyTest{publicstaticvoidmain(String[]args){//创建一个统计任务并指定IDStopWatchstopWatch=newStopWatch("Mainmethodtakestime");IntStream.rangeClosed(1,10).forEach(index->{//开始计时并指定任务名称,方便显示stopWatch.start("task"+index);//休眠100ms,模拟任务耗时try{线程.sleep(100L);}catch(InterruptedExceptione){}//endtimingstopWatch.stop();});//printstatisticalresultsSystem.out.println(stopWatch.prettyPrint());}}Theoutputresultis:StopWatch'Mainmethodtime-consuming':runningtime(millis)=1039--------------------------------------------ms%Taskname-----------------------------------------00103010%task100107010%task200104010%task300104010%task400105010%task500102010%task600104010%task700102010%task800105010%task900103010%task10打印出了每个任务的耗时,并统计了在总耗时所Asapercentage,itisalreadyveryintuitive这怎么可能?其实源码很简单,用一个LinkedList记录每个任务的耗时:publicclassStopWatch{//totaltaskIDprivatefinalStringid;//任务集合privatefinalListtaskList=newLinkedList();私人长启动时间毫秒;私人布尔运行;私有字符串当前任务名称;私有任务信息lastTaskInfo;私人长总时间毫秒;公共秒表(){这个(“”);start()抛出IllegalStateException{start("");}//开始计时,记录开始时间}this.running=true;this.currentTaskName=taskName;this.startTimeMillis=System.currentTimeMillis();}//结束计时,统计耗时,加入taskListpublicvoidstop()throwsIllegalStateException{if(!this.running){thrownewIllegalStateException("无法停止秒表:它没有运行");}longlastTime=System.currentTimeMillis()-this.startTimeMillis;this.totalTimeMillis+=lastTime;this.lastTaskInfo=newTaskInfo(this.currentTaskName,lastTime);this.taskList.add(lastTaskInfo);这个。运行=假;this.currentTaskName=null;}publiclonggetLastTaskTimeMillis()throwsIllegalStateException{if(this.lastTaskInfo==null){thrownewIllegalStateException("Notasksrun:can'tgetlasttaskinterval");}返回this.lastTaskInfo.getTimeMillis();}publicStringgetLastTaskName()throwsIllegalStateException{if(this.lastTaskInfo==null){thrownewIllegalStateException("没有任务运行:无法获取最后一个任务名称");}返回this.lastTaskInfo.getTaskName();}publicdoublegetTotalTimeSeconds(){returnthis.totalTimeMillis/1000.0;}publicTaskInfo[]getTaskInfo(){returnthis.taskList.toArray(newTaskInfo[this.taskList.size()]);}publicStringshortSummary(){return"StopWatch'"+getId()+"':运行时间(millis)="+getTotalTimeMillis();}//打印统计结果publicStringprettyPrint(){StringBuildersb=newStringBuilder(shortSummary());sb.append('\n');sb.append("----------------------------------------\n");sb.append("ms%任务名称\n");sb.append("----------------------------------------\n");NumberFormatnf=NumberFormat.getNumberInstance();nf.setMinimumIntegerDigits(5);nf.setGroupingUsed(false);NumberFormatpf=NumberFormat.getPercentInstance();pf.setMinimumIntegerDigits(3);pf.setGroupingUsed(false);for(TaskInfotask:getTaskInfo()){sb.append(nf.format(task.getTimeMillis())).append("");sb.append(pf.format(task.getTimeSeconds()/getTotalTimeSeconds())).append("");sb.append(task.getTaskName()).append("\n");}返回sb.toString();}publicstaticfinalclassTaskInfo{privatefinalStringtaskName;privatefinallongtimeMillis;TaskInfo(StringtaskName,longtimeMillis){this.taskName=taskName;this.timeMillis=timeMillis;}}}感觉怎么样?赶快使用起来吧