2011-09-14 23 views
1

Java性能問題,我有一個在使用StringTokenizer是長的StringTokenizer

本來StringTokenizer包含約1500令牌和程序工作正常原始文本String讀取和處理數據的程序。但是原始內容增加了,現在它變成了大約12,000個令牌,並且CPU消耗大大增加。

我在調查問題並嘗試找出根本原因。該程序使用while循環來檢查是否還有任何令牌,並根據讀取的令牌採取不同的操作。我正在檢查這些不同的行動,看看這些行動是否可以改善。

同時我想問一下,如果處理一個長度爲StringTokenizer的CPU會比處理10個短的StringTokenizer s花費更多的CPU。

+8

你確定它是StringTokenizer,而不是你*在做什麼*與它?請顯示一個簡短但完整的程序來說明問題。 –

+0

我不這麼認爲。字符串是隨機訪問的,對於長字符串不應該減速。 – Thilo

+1

「StringTokenizer」中沒有任何內容會導致長時間輸入。它必須是周圍代碼中的東西。 – Barend

回答

0

爲什麼不嘗試更新的Scanner類呢?掃描儀可以使用流和文件構建。不過不知道它比舊的StringTokenizer更有效率。

1

根據StringTokenizer java doc,不鼓勵StringTokenizer的使用。 儘管可以使用它,但它並未被棄用。只有它不被推薦。這裏是寫的是:

「的StringTokenizer是保留兼容性 原因,雖然它的使用是在新代碼氣餒遺留類建議 ,任何人尋求此功能使用字符串 的分割方法。或者改爲java.util.regex包。「

請檢查以下內容。它有很多不同的方式來做你想做的事情。

performance-of-stringtokenizer-class-vs-split-method-in-java

你可以試試只要有樣品,看看什麼最適合你。

+0

謝謝A.J. 您的推薦帖子對解決我的問題非常有幫助。 –

1

首先,感謝您的意見。在上個週末,我使用修改過的程序對真實數據進行了壓力測試,很高興我的問題得到了解決(非常感謝A.J.^_ ^)。我想分享我的發現。

在研究了A.J.提到的例子之後,我運行了一些測試程序來使用StringTokenizer和「indexOf」讀取和處理數據(在我的情況下,Regex與StringTokenizer相比甚至更差)。我的測試程序會計算需要多少微秒來處理24條消息(每條消息約12000個令牌)。

StringTokenizer需要〜2700ms才能完成,而「indexOf」只需要〜210ms!

我再修改我的計劃是這樣的(以最小的變化)和上週末期間與實際量測試:

原程序:

public class MsgProcessor { 
    //Some other definition and methods ... 

    public void processMessage (String msg) 
    { 
     //... 

     StringTokenizer token = new StringTokenizer(msg, FieldSeparator); 
     while (token.hasMoreTokens()) { 
      my_data = token.nextToken(); 
      // peformance different action base on token read 
     } 
    } 
} 

這裏使用的更新程序「的indexOf」:

public class MsgProcessor { 
    //Some other definition and methods ... 
    private int tokenStart=0; 
    private int tokenEnd=0; 

    public void processMessage (String msg) 
    { 
     //... 
     tokenStart=0; 
     tokenEnd=0; 

     while (isReadingData) { 
      my_data = getToken(msg); 
      if (my_data == null) 
       break; 
      // peformance different action base on token read ... 
     } 
    } 

    private String getToken (String msg) 
    { 
     String result = null; 
     if ((tokenEnd = msg.indexOf(FieldSeparator, tokenStart)) >= 0) { 
      result = msg.substring(tokenStart, tokenEnd); 
      tokenStart = tokenEnd + 1; 
     } 
     return result; 
    } 
} 
  • 請注意原始標記中沒有「空」數據。如果沒有找到FieldSeparator,「getToken(msg)」將返回null(作爲「沒有更多標記」的信號)。