0

我正在玩Java內核,並編寫了一段代碼以並行方式計算一些東西。數據基本上由一個Map組成,每個Map都有一個數值列表作爲值。我的目標是總結此地圖中所有鍵的所有值。 首先,我認爲在一個單獨的線程中獲取每個鍵的所有值的總和(每個鍵都有它自己的單獨線程)是一個好主意,並且最後我將每個線程返回的內容相加以得到總數。我用一個簡單CounDownLatch在我的代碼:如何讓我的算法使用Java CountDownLatch並行處理?

public static void main(String[] args) throws InterruptedException, ExecutionException 
    { 
     //final CountDownLatch startGate = new CountDownLatch(1); 
     final CountDownLatch endGate = new CountDownLatch(3); 


     Map> data = new HashMap>(); 
     Set summedData = new HashSet(); 
     // populate the map with data 
     populateMap(data); 
     //separate the data with keys 
     //send each list to a new thread to process 

     for (String key : data.keySet()) 
     { 
      final List list = data.get(key); 
      System.out.println(list); 

      //create a FutureTask 
      FutureTask future = new FutureTask(new Callable() 
      { 

       @Override 
       public Integer call() throws Exception 
       { 
        int sum = new Mapx(list).getSum(); 
        endGate.countDown(); 
        return sum; 
       } 
      }); 

      Thread t = new Thread(future); 
      t.start(); 
      System.out.println(t.getState()); 
      summedData.add(future.get()); 
     } 
     //keep the main method on hold until all the thread do their job 
     endGate.await(); 
     //send to reduce 
     int total = new Reduce(summedData).addAll(); 
     System.out.println(total); 

    }

我的期望是,如果在列表中的所有項目總結了關鍵的計算需要很長,對於這個關鍵運行的線程,在後臺運行另一個用於下一個鍵的線程開始計算。換句話說,計算是並行完成的。但是,我發現情況並非如此,線程是以串行方式運行的。有人可以幫助我如何實現我的目標並使這段代碼平行嗎?

回答

4

你叫future.get()從內環路。這個方法會阻塞直到結果被計算出來,因此直到另一個線程完成計算纔會繼續循環,從而導致你得到的序列化行爲。

爲了獲得您想要的行爲,您應該有一個循環啓動線程上的所有futureTasks,然後使用get()從所有FutureTask獲得結果的循環。

您可能更適合向ExecutorService提交Callable(請參閱Executors),並且ExecutorService將爲您提供Future

實際上並行啓動計算並等待其結果是ExectorServiceinvokeAll()方法爲您所做的。

使用CountDownLatch是多餘的,因爲Future對象已經在板上具有必要的同步行爲。

0

只是想補充一點,這種並行處理將只需要如果您的處理器至少是雙核的時間更少。如果你有一個核心處理器,那麼這種方法實際上可能需要更多時間