日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Java程序性能優(yōu)化Tip

 WindySky 2016-06-24

本博客是閱讀<java time and space performance tips>這本小書后整理的讀書筆記性質(zhì)博客,增加了幾個(gè)測(cè)試代碼,代碼可以在此下載:java時(shí)空間性能優(yōu)化測(cè)試代碼 ,文件StopWatch是一個(gè)秒表計(jì)時(shí)工具類,它的代碼在文末。

1. 時(shí)間優(yōu)化

1.1 標(biāo)準(zhǔn)代碼優(yōu)化

a. 將循環(huán)不變量的計(jì)算移出循環(huán)

    我寫了一個(gè)測(cè)試?yán)尤缦拢?/p>

復(fù)制代碼
import util.StopWatch;

/**
 * 循環(huán)優(yōu)化:
 * 除了本例中將循環(huán)不變量移出循環(huán)外,還有將忙循環(huán)放在外層
 * @author jxqlovejava
 *
 */
public class LoopOptimization {
    
    public int size() {
        try {
            Thread.sleep(200);   // 模擬耗時(shí)操作
        }
        catch(InterruptedException ie) {
            
        }
        
        return 10;
    }
    
    public void slowLoop() {
        StopWatch sw = new StopWatch("slowLoop");
        sw.start();
        
        for(int i = 0; i < size(); i++);
        
        sw.end();
        sw.printEclapseDetail();
    }
    
    public void optimizeLoop() {
        StopWatch sw = new StopWatch("optimizeLoop");
        sw.start();
        
        // 將循環(huán)不變量移出循環(huán)
        for(int i = 0, stop = size(); i < stop; i++);
        
        sw.end();
        sw.printEclapseDetail();
    }
    
    public static void main(String[] args) {
        LoopOptimization loopOptimization = new LoopOptimization();
        loopOptimization.slowLoop();
        loopOptimization.optimizeLoop();
    }

}
復(fù)制代碼

    測(cè)試結(jié)果如下:

slowLoop任務(wù)耗時(shí)(毫秒):2204
optimizeLoop任務(wù)耗時(shí)(毫秒):211

    可以很清楚地看到不提出循環(huán)不變量比提出循環(huán)不變量要慢10倍,在循環(huán)次數(shù)越大并且循環(huán)不變量的計(jì)算越耗時(shí)的情況下,這種優(yōu)化會(huì)越明顯。

b. 避免重復(fù)計(jì)算

    這條太常見,不舉例了

c. 盡量減少數(shù)組索引訪問次數(shù),數(shù)組索引訪問比一般的變量訪問要慢得多

    數(shù)組索引訪問比如int i = array[0];需要進(jìn)行一次數(shù)組索引訪問(和數(shù)組索引訪問需要檢查索引是否越界有關(guān)系吧)。這條Tip經(jīng)過我的測(cè)試發(fā)現(xiàn)效果不是很明顯(但的確有一些時(shí)間性能提升),可能在數(shù)組是大數(shù)組、循環(huán)次數(shù)比較多的情況下更明顯。測(cè)試代碼如下:

復(fù)制代碼
import util.StopWatch;

/**
 * 數(shù)組索引訪問優(yōu)化,尤其針對(duì)多維數(shù)組
 * 這條優(yōu)化技巧對(duì)時(shí)間性能提升不太明顯,而且可能降低代碼可讀性
 * @author jxqlovejava
 *
 */
public class ArrayIndexAccessOptimization {
    
    private static final int m = 9;   // 9行
    private static final int n = 9;   // 9列
    private static final int[][] array = {
        { 1,  2,  3,  4,  5,  6,  7,   8, 9  },
        { 11, 12, 13, 14, 15, 16, 17, 18, 19 },
        { 21, 22, 23, 24, 25, 26, 27, 28, 29 },
        { 31, 32, 33, 34, 35, 36, 37, 38, 39 },
        { 41, 42, 43, 44, 45, 46, 47, 48, 49 },
        { 51, 52, 53, 54, 55, 56, 57, 58, 59 },
        { 61, 62, 63, 64, 65, 66, 67, 68, 69 },
        { 71, 72, 73, 74, 75, 76, 77, 78, 79 },
        { 81, 82, 83, 84, 85, 86, 87, 88, 89 },
        { 91, 92, 93, 94, 95, 96, 97, 98, 99 }
    };   // 二維數(shù)組
    

    public void slowArrayAccess() {
        StopWatch sw = new StopWatch("slowArrayAccess");
        sw.start();
        
        for(int k = 0; k < 10000000; k++) {
            int[] rowSum = new int[m];
            for(int i = 0; i < m; i++) {
                for(int j = 0; j < n; j++) {
                    rowSum[i] += array[i][j];
                }
            }
        }

        sw.end();
        sw.printEclapseDetail();
    }
    
    public void optimizeArrayAccess() {
        StopWatch sw = new StopWatch("optimizeArrayAccess");
        sw.start();
        
        for(int k = 0; k < 10000000; k++) {
            int[] rowSum = new int[n];
            for(int i = 0; i < m; i++) {
                int[] arrI = array[i];
                int sum = 0;
                for(int j = 0; j < n; j++) {
                    sum += arrI[j];
                }
                rowSum[i] = sum;
            }
        }
        
        sw.end();
        sw.printEclapseDetail();
    }
    
    public static void main(String[] args) {
        ArrayIndexAccessOptimization arrayIndexAccessOpt = new ArrayIndexAccessOptimization();
        arrayIndexAccessOpt.slowArrayAccess();
        arrayIndexAccessOpt.optimizeArrayAccess();
    }
    
}
復(fù)制代碼

d. 將常量聲明為final static或者final,這樣編譯器就可以將它們內(nèi)聯(lián)并且在編譯時(shí)就預(yù)先計(jì)算好它們的值

e. 用switch-case替代冗長(zhǎng)的if-else-if

    測(cè)試代碼如下,但優(yōu)化效果不明顯:

復(fù)制代碼
import util.StopWatch;

/**
 * 優(yōu)化效果不明顯
 * @author jxqlovejava
 *
 */
public class IfElseOptimization {
    
    public void slowIfElse() {
        StopWatch sw = new StopWatch("slowIfElse");
        sw.start();
        
        for(int k = 0; k < 2000000000; k++) {
            int i = 9;
            if(i == 0) { }
            else if(i == 1) { }
            else if(i == 2) { }
            else if(i == 3) { }
            else if(i == 4) { }
            else if(i == 5) { }
            else if(i == 6) { }
            else if(i == 7) { }
            else if(i == 8) { }
            else if(i == 9) { }
        }
        
        sw.end();
        sw.printEclapseDetail();
    }
    
    public void optimizeIfElse() {
        StopWatch sw = new StopWatch("optimizeIfElse");
        sw.start();
        
        for(int k = 0; k < 2000000000; k++) {
            int i = 9;
            switch(i) {
            case 0:
                break;
            case 1:
                break;
            case 2:
                break;
            case 3:
                break;
            case 4:
                break;
            case 5:
                break;
            case 6:
                break;
            case 7:
                break;
            case 8:
                break;
            case 9:
                break;
            default:
            }
        }
        
        sw.end();
        sw.printEclapseDetail();
    }
    
    public static void main(String[] args) {
        IfElseOptimization ifElseOpt = new IfElseOptimization();
        ifElseOpt.slowIfElse();
        ifElseOpt.optimizeIfElse();
    }

}
復(fù)制代碼

f. 如果冗長(zhǎng)的if-else-if無法被switch-case替換,那么可以使用查表法優(yōu)化

 

1.2 域和變量?jī)?yōu)化

a. 訪問局部變量和方法參數(shù)比訪問實(shí)例變量和類變量要快得多

b. 在嵌套的語(yǔ)句塊內(nèi)部或者循環(huán)內(nèi)部生命變量并沒有什么運(yùn)行時(shí)開銷,所以應(yīng)該盡量將變量聲明得越本地化(local)越好,這甚至?xí)兄诰幾g器優(yōu)化你的程序,也提高了代碼可讀性

 

1.3 字符串操作優(yōu)化

a. 避免頻繁地通過+運(yùn)算符進(jìn)行字符串拼接(老生常談),因?yàn)樗鼤?huì)不斷地生成新字符串對(duì)象,而生成字符串對(duì)象不僅耗時(shí)而且耗內(nèi)存(一些OOM錯(cuò)誤是由這種場(chǎng)景導(dǎo)致的)。而要使用StringBuilder的append方法

b. 但對(duì)于這種String s = "hello" + " world"; 編譯器會(huì)幫我們優(yōu)化成String s = "hello world";實(shí)際上只生成了一個(gè)字符串對(duì)象"hello world",所以這種沒關(guān)系
c. 避免頻繁地對(duì)字符串對(duì)象調(diào)用substring和indexOf方法

 

1.4 常量數(shù)組優(yōu)化

a. 避免在方法內(nèi)部聲明一個(gè)只包含常量的數(shù)組,應(yīng)該把數(shù)組提為全局常量數(shù)組,這樣可以避免每次方法調(diào)用都生成數(shù)組對(duì)象的時(shí)間開銷

b. 對(duì)于一些耗時(shí)的運(yùn)算比如除法運(yùn)算、MOD運(yùn)算、Log運(yùn)算,可以采用預(yù)先計(jì)算值來優(yōu)化

 

1.5 方法優(yōu)化

a. 被private final static修飾的方法運(yùn)行更快
b. 如果確定一個(gè)類的方法不需要被子類重寫,那么將方法用final修飾,這樣更快
c. 盡量使用接口作為方法參數(shù)或者其他地方,而不是接口的具體實(shí)現(xiàn),這樣也更快

 

1.6 排序和查找優(yōu)化

a. 除非數(shù)組或者鏈表元素很少,否則不要使用選擇排序、冒泡排序和插入排序。使用堆排序、歸并排序和快速排序。

b. 更推薦的做法是使用JDK標(biāo)準(zhǔn)API內(nèi)置的排序方法,時(shí)間復(fù)雜度為O(nlog(n))
    對(duì)數(shù)組排序用Arrays.sort(它的實(shí)現(xiàn)代碼使用改良的快速排序算法,不會(huì)占用額外內(nèi)存空間,但是不穩(wěn)定)
    對(duì)鏈表排序用Collections.sort(穩(wěn)定算法,但會(huì)使用額外內(nèi)存空間)
c. 避免對(duì)數(shù)組和鏈表進(jìn)行線性查找,除非你明確知道要查找的次數(shù)很少或者數(shù)組和鏈表長(zhǎng)度很短
    對(duì)于數(shù)組使用Arrays.binarySearch,但前提是數(shù)組已經(jīng)有序,并且數(shù)組如包含多個(gè)要查找的元素,不能保證返回哪一個(gè)的index
    對(duì)于鏈表使用Collections.binarySearch,前提也是鏈表已經(jīng)有序
    使用哈希查找:HashSet<T>、HashMap<K, V>等
    使用二叉查找樹:TreeSet<T>和TreeMap<K, V>,一般要提供一個(gè)Comparator作為構(gòu)造函數(shù)參數(shù),如果不提供則按照自然順序排序

 

1.7 Exception優(yōu)化

a. new Exception(...)會(huì)構(gòu)建一個(gè)異常堆棧路徑,非常耗費(fèi)時(shí)間和空間,尤其是在遞歸調(diào)用的時(shí)候。創(chuàng)建異常對(duì)象一般比創(chuàng)建普通對(duì)象要慢30-100倍。自定義異常類時(shí),層級(jí)不要太多。

b. 可以通過重寫Exception類的fillInStackTrace方法而避免過長(zhǎng)堆棧路徑的生成

復(fù)制代碼
class MyException extends Exception {
    
    /**
     * 
     */
    private static final long serialVersionUID = -1515205444433997458L;

    public Throwable fillInStackTrace() {
        return this;
    }
    
}
復(fù)制代碼

c. 所以有節(jié)制地使用異常,不要將異常用于控制流程、終止循環(huán)等。只將異常用于意外和錯(cuò)誤場(chǎng)景(文件找不到、非法輸入格式等)。盡量復(fù)用之前創(chuàng)建的異常對(duì)象。

 

1.8 集合類優(yōu)化

a. 如果使用HashSet或者HashMap,確保key對(duì)象有一個(gè)快速合理的hashCode實(shí)現(xiàn),并且要遵守hashCode和equals實(shí)現(xiàn)規(guī)約
b. 如果使用TreeSet<T>或者TreeMap<K, V>,確保key對(duì)象有一個(gè)快速合理的compareTo實(shí)現(xiàn);或者在創(chuàng)建TreeSet<T>或者TreeMap<K, V>時(shí)顯式提供一個(gè)Comparator<T>
c. 對(duì)鏈表遍歷優(yōu)先使用迭代器遍歷或者for(T x: lst),for(T x: lst)隱式地使用了迭代器來遍歷鏈表。而對(duì)于數(shù)組遍歷優(yōu)先使用索引訪問:for(int i = 0; i < array.length; i++) 

d. 避免頻繁調(diào)用LinkedList<T>或ArrayList<T>的remove(Object o)方法,它們會(huì)進(jìn)行線性查找
e. 避免頻繁調(diào)用LinkedList<T>的add(int i, T x)和remove(int i)方法,它們會(huì)執(zhí)行線性查找來確定索引為i的元素

f. 最好避免遺留的集合類如Vector、Hashtable和Stack,因?yàn)樗鼈兊乃蟹椒ǘ加胹ynchronized修飾,每個(gè)方法調(diào)用都必須先獲得對(duì)象內(nèi)置鎖,增加了運(yùn)行時(shí)開銷。如果確實(shí)需要一個(gè)同步的集合,使用synchronziedCollection以及其他類似方法,或者使用ConcurrentHashMap

 

1.9 IO優(yōu)化

a. 使用緩沖輸入和輸出(BufferedReader、BufferedWriter、BufferedInputStream和BufferedOutputStream)可以提升IO速度20倍的樣子,我以前寫過一個(gè)讀取大文件(9M多,64位Mac系統(tǒng),8G內(nèi)存)的代碼測(cè)試?yán)?,如下?/p>

復(fù)制代碼
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import util.StopWatch;
 
public class ReadFileDemos {
    public static void main(String[] args) throws IOException {
        String filePath = "C:\\Users\\jxqlovejava\\workspace\\PerformanceOptimization\\test.txt";
        InputStream in = null;
        BufferedInputStream bis = null;
        File file = null;
        StopWatch sw = new StopWatch();
 
        sw.clear();
        sw.setTaskName("一次性讀取到字節(jié)數(shù)組+BufferedReader");
        sw.start();
        file = new File(filePath);
        in = new FileInputStream(filePath);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        char[] charBuf = new char[(int) file.length()];
        br.read(charBuf);
        br.close();
        in.close();
        sw.end();
        sw.printEclapseDetail();
        
        sw.clear();
        sw.setTaskName("一次性讀取到字節(jié)數(shù)組");
        sw.start();
        in = new FileInputStream(filePath);
        byte[] buf = new byte[in.available()];
        in.read(buf);// read(byte[] buf)方法重載
        in.close();
        for (byte c : buf) {
        }
        sw.end();
        sw.printEclapseDetail();

        sw.clear();
        sw.setTaskName("BufferedInputStream逐字節(jié)讀取");
        sw.start();
        in = new FileInputStream(filePath);
        bis = new BufferedInputStream(in);
        int b;
        while ((b = bis.read()) != -1);
        in.close();
        bis.close();
        sw.end();
        sw.printEclapseDetail();

        sw.clear();
        sw.setTaskName("BufferedInputStream+DataInputStream分批讀取到字節(jié)數(shù)組");
        sw.start();
        in = new FileInputStream(filePath);
        bis = new BufferedInputStream(in);
        DataInputStream dis = new DataInputStream(bis);
        byte[] buf2 = new byte[1024*4]; // 4k per buffer
        int len = -1;
        StringBuffer sb = new StringBuffer();
        while((len=dis.read(buf2)) != -1 ) {
            // response.getOutputStream().write(b, 0, len);
            sb.append(new String(buf2));
        }
        dis.close();
        bis.close();
        in.close();
        sw.end();
        sw.printEclapseDetail();

        sw.clear();
        sw.setTaskName("FileInputStream逐字節(jié)讀取");
        sw.start();
        in = new FileInputStream(filePath);
        int c;
        while ((c = in.read()) != -1);
        in.close();
        sw.end();
        sw.printEclapseDetail();
    }
}
復(fù)制代碼

    結(jié)果如下:

一次性讀取到字節(jié)數(shù)組+BufferedReader任務(wù)耗時(shí)(毫秒):121
一次性讀取到字節(jié)數(shù)組任務(wù)耗時(shí)(毫秒):23
BufferedInputStream逐字節(jié)讀取任務(wù)耗時(shí)(毫秒):408
BufferedInputStream+DataInputStream分批讀取到字節(jié)數(shù)組任務(wù)耗時(shí)(毫秒):147
FileInputStream逐字節(jié)讀取任務(wù)耗時(shí)(毫秒):38122

b. 將文件壓縮后存到磁盤,這樣讀取時(shí)更快,雖然會(huì)耗費(fèi)額外的CPU來進(jìn)行解壓縮。網(wǎng)絡(luò)傳輸時(shí)也盡量壓縮后傳輸。Java中壓縮有關(guān)的類:ZipInputStream、ZipOutputStream、GZIPInputStream和GZIPOutputStream

 

1.10 對(duì)象創(chuàng)建優(yōu)化

a. 如果程序使用很多空間(內(nèi)存),它一般也將耗費(fèi)更多的時(shí)間:對(duì)象分配和垃圾回收需要耗費(fèi)時(shí)間、使用過多內(nèi)存可能導(dǎo)致不能很好利用CPU緩存甚至可能需要使用虛存(訪問磁盤而不是RAM)。而且根據(jù)JVM的垃圾回收器的不同,使用太多內(nèi)存可能導(dǎo)致長(zhǎng)時(shí)間的回收停頓,這對(duì)于交互式系統(tǒng)和實(shí)時(shí)應(yīng)用是不能忍受的。

b. 對(duì)象創(chuàng)建需要耗費(fèi)時(shí)間(分配內(nèi)存、初始化、垃圾回收等),所以避免不必要的對(duì)象創(chuàng)建。但是記住不要輕易引入對(duì)象池除非確實(shí)有必要。大部分情況,使用對(duì)象池僅僅會(huì)導(dǎo)致代碼量增加和維護(hù)代價(jià)增大,并且對(duì)象池可能引入一些微妙的問題

c. 不要?jiǎng)?chuàng)建一些不會(huì)被使用到的對(duì)象

 

1.11 數(shù)組批量操作優(yōu)化

數(shù)組批量操作比對(duì)數(shù)組進(jìn)行for循環(huán)要快得多,部分原因在于數(shù)組批量操作只需進(jìn)行一次邊界檢查,而對(duì)數(shù)組進(jìn)行for循環(huán),每一次循環(huán)都必須檢查邊界。

a. System.arrayCopy(src, si, dst, di, n) 從源數(shù)組src拷貝片段[si...si+n-1]到目標(biāo)數(shù)組dst[di...di+n-1]

b. boolean Arrays.equals(arr1, arr2) 返回true,當(dāng)且僅當(dāng)arr1和arr2的長(zhǎng)度相等并且元素一一對(duì)象相等(equals)

c. void Arrays.fill(arr, x) 將數(shù)組arr的所有元素設(shè)置為x

d. void Arrays.fill(arr, i, j x) 將數(shù)組arr的[i..j-1]索引處的元素設(shè)置為x

e. int Arrays.hashCode(arr) 基于數(shù)組的元素計(jì)算數(shù)組的hashcode

 

1.12 科學(xué)計(jì)算優(yōu)化

Colt(http://acs./software/colt/)是一個(gè)科學(xué)計(jì)算開源庫(kù),可以用于線性代數(shù)、稀疏和緊湊矩陣、數(shù)據(jù)分析統(tǒng)計(jì),隨機(jī)數(shù)生成,數(shù)組算法,代數(shù)函數(shù)和復(fù)數(shù)等。

 

1.13 反射優(yōu)化

a. 通過反射創(chuàng)建對(duì)象、訪問屬性、調(diào)用方法比一般的創(chuàng)建對(duì)象、訪問屬性和調(diào)用方法要慢得多

b. 訪問權(quán)限檢查(反射調(diào)用private方法或者反射訪問private屬性時(shí)會(huì)進(jìn)行訪問權(quán)限檢查,需要通過setAccessible(true)來達(dá)到目的)可能會(huì)讓反射調(diào)用方法更慢,可以通過將方法聲明為public來比避免一些開銷。這樣做之后可以提高8倍。

 

1.14 編譯器和JVM平臺(tái)優(yōu)化

a. Sun公司的HotSpot Client JVM會(huì)進(jìn)行一些代碼優(yōu)化,但一般將快速啟動(dòng)放在主動(dòng)優(yōu)化之前進(jìn)行考慮

b. Sun公司的HotSpot Server JVM(-server選項(xiàng),Windows平臺(tái)無效)會(huì)進(jìn)行一些主動(dòng)優(yōu)化,但可能帶來更長(zhǎng)的啟動(dòng)延遲

c. IBM的JVM也會(huì)進(jìn)行一些主動(dòng)優(yōu)化

d. J2ME和一些手持設(shè)備(如PDA)不包含JIT編譯,很可能不會(huì)進(jìn)行任何優(yōu)化

 

1.15 Profile

 

2. 空間優(yōu)化

2.1 堆(對(duì)象)和棧(方法參數(shù)、局部變量等)。堆被所有線程共享,但棧被每個(gè)線程獨(dú)享

 

2.2 空間消耗的三個(gè)重要方面是:Allocation Rate(分配頻率)、Retention(保留率)和Fragmentation(內(nèi)存碎片)
      Allocation Rate是程序創(chuàng)建新對(duì)象的頻率,頻率越高耗費(fèi)的時(shí)間和空間越多。
      Retention是存活的堆數(shù)據(jù)數(shù)量。這個(gè)值越高需要耗費(fèi)越多的空間和時(shí)間(垃圾回收器執(zhí)行分配和去分配工作時(shí)需要進(jìn)行更多的管理工作)
      Fragmentation:內(nèi)存碎片是指小塊無法使用的內(nèi)存。如果一直持續(xù)創(chuàng)建大對(duì)象,可能會(huì)引起過多的內(nèi)存碎片。從而需要更多的時(shí)間分配內(nèi)存(因?yàn)橐檎乙粋€(gè)足夠大的連續(xù)可用內(nèi)存塊),并且會(huì)浪費(fèi)更多的空間因?yàn)閮?nèi)存碎片無法被利用。當(dāng)然某些GC算法可以避免過多內(nèi)存碎片的產(chǎn)生,但相應(yīng)的算法代價(jià)也較高。


2.3 內(nèi)存泄露


2.4 垃圾回收器的種類(分代收集、標(biāo)記清除、引用計(jì)數(shù)、增量收集、壓縮...)對(duì)Allocation Rate、Retention和Fragmentation的時(shí)間空間消耗影響很大


2.5 對(duì)象延遲創(chuàng)建

 

附上StopWatch計(jì)時(shí)工具類:

復(fù)制代碼
/**
 * 秒表類,用于計(jì)算執(zhí)行時(shí)間
 * 注意該類是非線程安全的
 * @author jxqlovejava
 *
 */
public class StopWatch {
    
    private static final String DEFAULT_TASK_NAME = "defaultTask";
    private String taskName;
    private long start, end;
    private boolean hasStarted, hasEnded;
    
    // 時(shí)間單位枚舉:毫秒、秒和分鐘
    public enum TimeUnit { MILLI, SECOND, MINUTE  }
    
    public StopWatch() {
        this(DEFAULT_TASK_NAME);
    }
    
    public StopWatch(String taskName) {
        this.taskName = StringUtil.isEmpty(taskName) ? DEFAULT_TASK_NAME : taskName;
    }
    
    public void start() {
        start = System.currentTimeMillis();
        hasStarted = true;
    }
    
    public void end() {
        if(!hasStarted) {
            throw new IllegalOperationException("調(diào)用StopWatch的end()方法之前請(qǐng)先調(diào)用start()方法");
        }
        end = System.currentTimeMillis();
        hasEnded = true;
    }
    
    public void clear() {
        this.start = 0;
        this.end = 0;
        
        this.hasStarted = false;
        this.hasEnded = false;
    }
    
    /**
     * 獲取總耗時(shí),單位為毫秒
     * @return 消耗的時(shí)間,單位為毫秒
     */
    public long getEclapsedMillis() {
        if(!hasEnded) {
            throw new IllegalOperationException("請(qǐng)先調(diào)用end()方法");
        }
        
        return (end-start);
    }
    
    /**
     * 獲取總耗時(shí),單位為秒
     * @return 消耗的時(shí)間,單位為秒
     */
    public long getElapsedSeconds() {
        return this.getEclapsedMillis() / 1000;
    }
    
    /**
     * 獲取總耗時(shí),單位為分鐘
     * @return 消耗的時(shí)間,單位為分鐘
     */
    public long getElapsedMinutes() {
        return this.getEclapsedMillis() / (1000*60);
    }
    
    public void setTaskName(String taskName) {
        this.taskName = StringUtil.isEmpty(taskName) ? DEFAULT_TASK_NAME : taskName;
    }
    
    public String getTaskName() {
        return this.taskName;
    }
    
    /**
     * 輸出任務(wù)耗時(shí)情況,單位默認(rèn)為毫秒
     */
    public void printEclapseDetail() {
        this.printEclapseDetail(TimeUnit.MILLI);
    }
    
    /**
     * 輸出任務(wù)耗時(shí)情況,可以指定毫秒、秒和分鐘三種時(shí)間單位
     * @param timeUnit 時(shí)間單位
     */
    public void printEclapseDetail(TimeUnit timeUnit) {
        switch(timeUnit) {
        case MILLI:
            System.out.println(this.getTaskName() + "任務(wù)耗時(shí)(毫秒):" + this.getEclapsedMillis());
            break;
        case SECOND:
            System.out.println(this.getTaskName() + "任務(wù)耗時(shí)(秒):" + this.getElapsedSeconds());
            break;
        case MINUTE:
            System.out.println(this.getTaskName() + "任務(wù)耗時(shí)(分鐘):" + this.getElapsedMinutes());
            break;
        default:
            System.out.println(this.getTaskName() + "任務(wù)耗時(shí)(毫秒):" + this.getEclapsedMillis());
        }
    }

}
復(fù)制代碼

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多