2016-09-28 6 views
1

У меня есть этот простой код, и это не экономит время. Время работы такое же, как при использовании одного потока. Что не так? Не могли бы вы помочь? Я новичок в этом, и я надеюсь, что этот вопрос не раздражает вас, если он слишком прост. Благодаря!Почему мой JAVA threadpool не экономит время?

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

В принципе, вы ожидаете, что результат вернется из Будущего вовремя к настоящему? Итак, вы можете начать несколько параллельных заданий и собрать свои результаты из будущего? –

ответ

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<> с и после того, как вы предоставите все они начинают называть их get() методы. Это позволит выполнять задачи параллельно.

+0

Понял, большое спасибо! –

+0

@JinpingShi Тогда, пожалуйста, «примите» ответ :) –

0

Как и Светлин Зарев, ваш будущий.get() блокирует, но если вы используете java 8, я бы рекомендовал посмотреть на CompleteableFuture, так как вы можете видеть все ваши потоки для запуска и использовать CompleteableFuture.allOf() для проверки что все они завершены и добавляются результаты после сделанного

 Смежные вопросы

  • Нет связанных вопросов^_^