2016-12-06 112 views
-1

我有這樣一段代碼:在這種情況下,多線程如何幫助提高性能?

while(){ 

    x = jdbc_readOperation(); 

    y = getTokens(x); 

    jdbc_insertOperation(y); 
} 

public List<String> getTokens(String divText){ 
    List<String> tokenList = new ArrayList<String>(); 
    Matcher subMatcher = Pattern.compile("\\[[^\\]]*]").matcher(divText); 
    while (subMatcher.find()) { 
     String token = subMatcher.group(); 
     tokenList.add(token); 
    } 
    return tokenList; 
} 

我所知道的是使用多線程可以節省時間,當一個線程被阻塞的I/O或網絡。在這個同步操作中,每一步都必須等待其前一步完成。我想在這裏最大限度地提高CPU利用率getTokens()

我首先想到的是把getTokens()一類的run方法,並創建多個線程。但我認爲它不會起作用,因爲通過在純計算操作中擁有多個線程似乎無法獲得性能優勢。

是採用多線程去幫助在這種情況下提高性能的?如果是這樣,我該怎麼做?

+1

試問如果「東西」被'some_stuff()'可以並行完成呢?或者,只有一個線程這樣做纔有意義? –

+0

沒有通用的方法來做到這一點。它完全依賴於'some_stuff()'的具體做法,以及程序中整體如何使用這些代碼。 –

+0

對不明確的含義,some_stuff()是一個字符串處理函數,唯一的參數來自讀操作的結果。我已經更新過。但我不確定是否可以在這種情況下「並行」完成,請您詳細說明一下嗎?謝謝。 – zonyang

回答

2

這將取決於該jdbc_readOperation()產生與步伐getTokens(x)的處理數據比較要處理的數據的步伐。知道這將幫助你弄清楚多線程是否會幫助你。

你可以嘗試這樣的事情(就是讓你的想法):

int workToBeDoneQueueSize = 1000; 
int workDoneQueueSize = 1000; 
BlockingQueue<String> workToBeDone = new LinkedBlockingQueue<>(workToBeDoneQueueSize); 
BlockingQueue<String> workDone = new LinkedBlockingQueue<>(workDoneQueueSize); 

new Thread(() -> { 
    try { 
     while (true) { 
      workToBeDone.put(jdbc_readOperation()); 
     } 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
     // handle InterruptedException here 
    } 
}).start(); 

int numOfWorkerThreads = 5; // just an example 
for (int i = 0; i < numOfWorkerThreads; i++) { 
    new Thread(() -> { 
     try { 
      while (true) { 
       workDone.put(getTokens(workToBeDone.take())); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
      // handle InterruptedException here 
     } 
    }).start(); 
} 

new Thread(() -> { 
    // you could improve this by making a batch operation 
    try { 
     while (true) { 
      jdbc_insertOperation(workDone.take()); 
     } 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
     // handle InterruptedException here 
    } 
}).start(); 

或者你可以學習如何使用的ThreadPoolExecutor。 (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html

+0

謝謝,這有助於很多。在這種情況下是否有任何理由使用LinkedBlockingQueue而不是ArrayBlockingQueue? – zonyang

+0

不,我不這麼認爲,你也可以使用。 –

0

好加快getTokens(),則可以通過使用String.substring()方法拆分輸入字符串divText。你將它分成許多子字符串,因爲你將運行運行getTokens()方法的線程。然後每個線程將「運行」在divText的某個子字符串上。

創建比CPU更多的線程可以處理應該避免的,因爲上下文切換導致無效率。

https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#substring-int-int-

的替代可以被分裂getTokens的輸入字符串與String.split方法http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split%28java.lang.String%29例如以防文字由空格或其他符號分隔的文字組成。然後,生成的字符串數組的特定部分可以傳遞給不同的線程。

+0

這不起作用。你如何預先確定你應該從哪些點採取子串?無論何時你使用子字符串,如果它們保持原樣,它可能會拆分可能與模式匹配的字符串。 –

+0

好點,分裂有點困難。你將不得不檢查文本中單詞的最大長度,並檢查你是否在那裏(前後)剪切。如果divText包含由空格分隔的單詞,則可以通過檢查空格來定位由最大單詞長度指定的區域來計算分割索引。 –