2016-09-28 36 views
1

我有這個簡單的代碼,它不會節省時間。運行時間與使用單線程相同。哪裏不對?你能幫忙嗎?我對此很陌生,如果它太簡單,我希望這個問題不會讓你煩惱。謝謝!爲什麼我的JAVA線程池不節省時間?

import java.util.Random; 
import java.util.concurrent.Callable; 
public class Work implements Callable<int[]> 
{ 
    int id; 
    int y; 

    public Work(int i) 
    { 
     id=i; 
    } 

    public int[] doit(){ 
     Random rand = new Random(); 
     y=rand.nextInt(10); 
     try { 
      Thread.sleep(y*1000);     //1000 milliseconds is one second. 
     } catch(InterruptedException ex) { 
      Thread.currentThread().interrupt(); 
      System.out.println(ex.getMessage()); 
     } 
     int x[] = new int[2]; 
     x[0]=id; 
     x[1]=y; 

     return x; 
    } 


    @Override 
    public int[] call() throws Exception 
    { 
     return doit(); 
    } 
} 
import java.text.SimpleDateFormat; 
import java.util.ArrayList; 
import java.util.Calendar; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
public class Driver 
{ 

    ArrayList<int[]> result=new ArrayList<int[]>() ; 
    public Driver() 
    { 
    } 

    public void doCalc(int n) 
    { 

     for (int i=0; i<n; i++) { 
      Work w = new Work(i); 
      int[] y = w.doit(); 


      if (y != null) { 
       result.add(y); 
      } 
     } 
     int total=0; 
     for (int i=0; i< result.size(); i++) { 
      System.out.println("id = " + result.get(i)[0] + "; random number = "+ result.get(i)[1]); 
      total+=result.get(i)[1]; 
     } 
     System.out.println("total = " + total); 
    } 
    public void doCalcThread(int n) 
    { 
     ExecutorService executor = Executors.newFixedThreadPool(5); 
     for (int i=0; i<n; i++) { 
      Work w = new Work(i); 
      Future<int[]> future =executor.submit(w); 
      int[] y; 
      try 
      { 
       y = future.get(); 
       if (y != null) { 
        result.add(y); 
       } 
      } catch (InterruptedException | ExecutionException e) 
      { 
       e.printStackTrace(); 
      } 

     } 
     executor.shutdown(); 
     while (!executor.isTerminated()) { 
     } 
     System.out.println("Finished all threads"); 

     int total=0; 
     for (int i=0; i< result.size(); i++) { 
      System.out.println("id = " + result.get(i)[0] + "; random number = "+ result.get(i)[1]); 
      total+=result.get(i)[1]; 
     } 
     System.out.println("total = " + total); 
    } 
    /** 
    * @param args 
    */ 
    public static void main(String[] args) 
    { 
     Driver dr = new Driver(); 
     Calendar cal = Calendar.getInstance(); 
     SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS"); 
     cal = Calendar.getInstance(); 
     System.out.println("before " + sdf.format(cal.getTime())); 

     //dr.doCalc(5); 
     dr.doCalcThread(5); 

     cal = Calendar.getInstance(); 
     System.out.println("after " + sdf.format(cal.getTime())); 
    } 
} 
+0

基本上,您希望結果能夠從Future回到現在?那麼你可以開始幾項平行工作並從未來收集他們的結果? –

回答

3

future.get();是一個等待計算完成的阻塞操作。所以基本上你在你的循環中每次啓動一個線程 - >不管任何並行。下面是錯誤代碼:

for (int i=0; i<n; i++) { 
      Work w = new Work(i); 
      Future<int[]> future =executor.submit(w); 
      int[] y; 
      try 
      { 
       y = future.get(); 
       if (y != null) { 
        result.add(y); 
       } 
      } catch (InterruptedException | ExecutionException e) 
      { 
       e.printStackTrace(); 
      } 

     } 

所以基本上你需要在列表中存儲所有Future<> S和您提交後所有的人都開始叫他們get()方法。這將允許任務並行運行。

+0

明白了,非常感謝! –

+0

@JinpingShi那麼請「接受」答案:) –

0

和Svetlin Zarev一樣,提到了你的future.get()是阻塞的,但是如果你使用的是java 8,我會建議看看CompleteableFuture,因爲你可以看到所有要運行的線程,並使用CompleteableFuture.allOf它們全部完成並在完成後添加結果