2013-10-10 184 views
0

我製作了一個程序,它使用單線程將文件中的數據讀入鏈接列表讓我們稱之爲LL1。從這裏我做了一個線程池,它爲每個線程分配一個處理任務,它從LL1讀取數據並將其計算結果輸出到一個新的鏈表中。 從這我需要輸出每個線程新的鏈接列表成一個單一的文件。我試圖輸出連續的塊,每個塊鏈表,使線程不混合的數據,所以我使用了一個同步點如下:帶線程池的Java線程隊列

public synchronized void appendContents(List<Vector2> output1) { 
    try { 
     sFileName = outFilePath + "\\file" +fileCount+ ".cntr"; 
     File oFile = new File(sFileName); 
     if (!oFile.exists()) { 
      oFile.createNewFile(); 
     } 
     if (oFile.canWrite()) { 
      //BufferedWriter oWriter = new BufferedWriter(new FileWriter(sFileName, true)); 
      FileWriter wstream = new FileWriter(oFile, true); 
      BufferedWriter outWriter = new BufferedWriter(wstream); 
      for(int i = 0; i < output1.size(); i++) 
      { 
       //replace the space marker values with a newline 
       if(output1.get(i).y == -200.0){ 
       outWriter.newLine(); 
       }else{ 
       outWriter.write(String.valueOf(output1.get(i).x) + " " + String.valueOf(output1.get(i).y) + " " + String.valueOf(interval)); 
       outWriter.newLine();  
       } 
      }   
      outWriter.close(); 
     } 
    } 
    catch (IOException oException) { 
     throw new IllegalArgumentException("Error appending/File cannot be written: \n" + sFileName); 
    } 

我面臨的問題是,數據不這就是我所需要的,即

list1 value        list1 value 
list1 value   _______________\  list2 value 
list1 value   ________________\ list1 value 
list2 value   RATHER THAN ____/ list3 value 
list2 value   ---------------/  list2 value 
list2 value        list1 value 
list3 value        list2 value 
list3 value        list1 value 
list3 value        list3 value 
list3 value        list3 value 

如果有人可以讓我在正確的方向邁出的一步,將不勝感激。 謝謝,

傑克

+0

向我們展示如何開始你的線程。還要澄清你得到的結果以及你的期望。 –

+0

也許這[示例](http://arashmd.blogspot.com/2013/07/java-thread-example.html#fe)將幫助 – 2013-10-10 05:29:12

+1

您需要同步訪問權限的資源是什麼?它似乎可能是'List '。您應該鎖定它,而不是使用appendContents()所屬對象的隱式鎖定。正如所寫,在高度併發的環境中,appendContents()方法可能會成爲瓶頸並限制可伸縮性。 – scottb

回答

2

的​​目的是共享資源同步,以便只有一個Thread獲得在單一時間訪問臨界區。我將假設您產生了三個Thread實例,每個實例都對其自己的對象調用appendContents

A​​方法隱式地在this上同步,但是因爲所有三個Thread都在不同的對象上同步,不同的this,沒有任何阻止他們。

1

據我所知,你每次運行每個列表元素的新任務?

然後您可以編寫Callable任務 - >將結果保存在List vs result(resultFeatureFromList)中的Feature.Put Feature中。並在最後做出這樣的事情: 我使用Guava Lib的函數;

Iterables.transform(resultList<Feature>,new Function(){ 
    public resultComputition apply(Feature resultFeatureFromList){ 
       return resultFeatureFromList.get(); 
    } 
}); 

因此,最後,您將按正確的順序運行所有任務。拉完後都只是等待結果。

1

user2870704's answer闡述,你可以按照如下構建應用程序:

  • 有一個線程讀取文件內容;
  • 對於文件中的每個項目,將Callable任務提交到您的線程池;
  • 將返回的Future存儲在列表或列表中 - 您可以定義所需的粒度;
  • 打開輸出文件,在同一線程中,遍歷結果列表進行寫操作。

舉個例子:

void readAndOutput(String inputFilePath, String outputFilePath) { 
    List<List<Future<Result>>> results = readAndSpawnTask(inputFilePath); 

    PrintWriter out = new PrintWriter(new File(outputFilePath)); 

    for (List<Future<Result>> block : results) { 
     for (Future<Result> r : block) { 
      out.println(r.get().toString()); 
     } 
    } 

    out.flush(); 
    out.close(); 
} 


List<List<Future<Result>>> readAndSpawnTask(String path) { 
    List<List<Future<Result>>> results = new ArrayList<>(numOfBlocks); 
    BufferedReader in = new BufferedReader(new FileReader(new File(path))); 

    for (int i = 0; i < numOfBlocks; ++i) { 
     results.add(new LinkedList<Future<Result>>()); 
    } 

    for (String line = in.readLine(); line != null; line = in.readLine()) { 
     int respectiveBlock; 
     Callable<Result> task; 
     // Process line and convert it into a task of your own. 
     // Determine in which block the result goes into. 
     Future<Result> r = threadPool.submit(task); 
     results.get(respectiveBlock).add(r); 
    } 

    in.close(); 

    return results; 
} 

如果你想和/或需要的併發,這個想法是訪問一個單獨的線程文件。使用Future列表,您可以保證以正確的順序編寫結果,並且您的主線程將會阻塞,直到所需的結果準備就緒。

當然,您仍然必須考慮上述代碼中可能出現的異常。