2013-08-13 6 views
11
ExecutorService pool=Executors.newFixedThreadPool(7); 
     List<Future<Hotel>> future=new ArrayList<Future<Hotel>>(); 
     List<Callable<Hotel>> callList = new ArrayList<Callable<Hotel>>(); 

     for(int i=0;i<=diff;i++){ 

      String str="2013-"+(liDates.get(i).get(Calendar.MONTH)+1)+"-"+liDates.get(i).get(Calendar.DATE); 

      callList.add(new HotelCheapestFare(str)); 

     }  
    future=pool.invokeAll(callList); 
for(int i=0;i<=future.size();i++){ 

     System.out.println("name is:"+future.get(i).get().getName()); 
    } 

今、私はループのため、このプログラムを実行すると、forループに入る前に、すべてのタスクinvokeAllにプールが、そのinvokeAll前に実行し、この例外をスローしますたい:道ExecutorService作品をinvokeAll()を使用してすべてのスレッドプールがそのタスクを実行する方法

java.util.concurrent.ExecutionException: java.lang.NullPointerException at 
java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source) at 
java.util.concurrent.FutureTask.get(Unknown Source) at 
com.mmt.freedom.cheapestfare.TestHotel.main(TestHotel.java:6‌​5) 

Caused by: java.lang.NullPointerException at 
com.mmt.freedom.cheapestfare.HotelCheapestFare.getHotelCheap‌estFare(HotelCheapes‌​tFare.java:166) 
at com.mmt.freedom.cheapestfare.HotelCheapestFare.call(HotelChe‌​apestFare.java:219) 
at com.mmt.freedom.cheapestfare.HotelCheapestFare.call(HotelChe‌​apestFare.java:1) 
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source) at java.util.concurrent.FutureTask.run(Unknown Source) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) atjava.util.concurrent.ThreadPoolExecutor$Worker.run(Unknow‌​n Source) 
at java.lang.Thread.run 
+0

すべての呼び出し可能オブジェクトが完了したまでInvokeAllを待つ必要があります。例外とスタックトレースを追加してください。 – jboi

+0

internalyいくつかのスレッドが完了する前にforループに行き、例外をスローする –

+0

私の仕事を提出しなければなりません –

答えて

11

ときにすべてのcompletその ステータスと結果を保持し、

が与えられたタスクを実行先物のリストを返す:あなたはinvokeAllを呼び出すときにすべてのタスクが完了することが待っていることですe。 Future.isDone()は返されたリストの各 要素に対して真です。 完了したタスクは、 を通常どおりに終了させるか、または例外をスローすることによって終了することに注意してください。 の結果は、指定されたコレクションが変更されていて、この操作が実行されている間に の場合、未定義です。 1(強調追加)

その手段は、あなたのタスクがすべて完了していることであるが、いくつかの例外をスローしている可能性がどのような。この例外はFutureの一部です。getを呼び出すと、例外が再スローされ、ExecutionExceptionにラップされます。

あなたは

java.util.concurrent.ExecutionException: java.lang.NullPointerException at 
java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source) at 
java.util.concurrent.FutureTask.get(Unknown Source) at 
           ^^^ <-- from get 

をstacktrackからあなたは、これは確かにそうであることがわかります。あなたのタスクの1つがNPEで失敗しました。 ExecutorServiceは例外をキャッチし、Future.getに電話するとExecutionExceptionを投げて通知します。

の完了時にのタスクを実行したい場合は、ExecutorCompletionServiceが必要です。これは、BlockingQueueのように機能し、タスクが終了した時点でポーリングすることができます。この例では

public static void main(String[] args) throws Exception { 
    final ExecutorService executorService = Executors.newFixedThreadPool(10); 
    final ExecutorCompletionService<String> completionService = new ExecutorCompletionService<>(executorService); 
    executorService.submit(new Runnable() { 
     @Override 
     public void run() { 
      for (int i = 0; i < 100; ++i) { 
       try { 
        final Future<String> myValue = completionService.take(); 
        //do stuff with the Future 
        final String result = myValue.get(); 
        System.out.println(result); 
       } catch (InterruptedException ex) { 
        return; 
       } catch (ExecutionException ex) { 
        System.err.println("TASK FAILED"); 
       } 
      } 
     } 
    }); 
    for (int i = 0; i < 100; ++i) { 
     completionService.submit(new Callable<String>() { 
      @Override 
      public String call() throws Exception { 
       if (Math.random() > 0.5) { 
        throw new RuntimeException("FAILED"); 
       } 
       return "SUCCESS"; 
      } 
     }); 
    } 
    executorService.shutdown(); 
} 

は、私は、彼らが利用可能になった後、私は ExecutorCompletionServiceにタスクを提出するよう Future秒を取得します ExecutorCompletionServicetakeを呼び出し、一つのタスクを持っています。

これにより、すべてのタスクが失敗して失敗するのを待つ必要はなく、失敗したタスクをすぐに取得できます。

唯一の問題は、すべてがすべて非同期であるため、すべてのタスクが完了したことをポーリングスレッドに伝えることが難しいことです。この例では、100回のタスクが100回ポーリングするだけで済むという知識を使用しました。より一般的な方法は、submitメソッドからFutureを収集し、それらのループを繰り返してすべてが完了したかどうかを確認することです。

+0

私はExecutorCompletionService を呼び出し可能なオブジェクトのリストと共に使用することができます –

+0

@SahilKohliいいえ、それは意味をなさない。 'ExecutorService'で' Collection'を使う理由は、**すべての**が処理を続ける前に終了するのを待つことができるからです。 'ExecutorCompletionService'を使って完了をポーリングしているので、それらを一度に、またはループですべて提出すれば何の違いもありません。 –

+0

私の仕事は時間がかかりますので、それらを同時に実行して、それらが同時に実行され、スレッドの完了後に将来の結果が得られるようにしてください。 –

-2

invokeAllはブロック方法です。つまり、JVMはすべてのスレッドが完了するまで次の行に進まない。だからあなたのスレッドの将来の結果に何か間違っていると思います。私はいくつかの先物があると思い、このラインから

System.out.println("name is:"+future.get(i).get().getName()); 

は何の結果を持っていないし、nullにすることができ、そのため、一部の先物がnullがある場合は、この行が実行前にあれば、入手もしそうなら、あなたは、あなたのコードを確認してください。

+0

これは間違っています。 stacktraceを見てください。 'Future.get'メソッドは' ExectuionExcetion'を投げています - それは明らかです。結果**は** 'ヌル 'ではありません。 'Callable'メソッドは' call'メソッドで 'NullPointerException'を検出しました。これは 'Future'で捕捉され、' ExectionException'でラップされます。 –

+0

申し訳ありませんが、私はjava.util.concurrent.ExecutionExceptionを見逃しました。 – Winston

+0

です –

4

Future.get()以下の例外をスローします。

CancellationException - 計算は

ExecutionExceptionをキャンセルされた場合 - あなたはget()メソッドを呼び出したときに、すべてのこれらの例外

キャッチを待っている間に、現在のスレッドが中断された場合 - 計算は例外

InterruptedExceptionを投げた場合。

私は、コード例に示すように、あなたは3つの例外の上にキャッチした場合ExecutorServiceに提出された他のCallableタスクに影響を与えないものCallableにゼロいくつかのCallableタスクの例外が、例外によって除算をシミュレートしています。

例のコードスニペット:

import java.util.concurrent.*; 
import java.util.*; 

public class InvokeAllUsage{ 
    public InvokeAllUsage(){ 
     System.out.println("creating service"); 
     ExecutorService service = Executors.newFixedThreadPool(10); 

     List<MyCallable> futureList = new ArrayList<MyCallable>(); 
     for (int i=0; i<10; i++){ 
      MyCallable myCallable = new MyCallable((long)i+1); 
      futureList.add(myCallable); 
     } 
     System.out.println("Start"); 
     try{ 
      List<Future<Long>> futures = service.invokeAll(futureList); 
      for(Future<Long> future : futures){ 
       try{ 
        System.out.println("future.isDone = " + future.isDone()); 
        System.out.println("future: call ="+future.get()); 
       } 
       catch (CancellationException ce) { 
        ce.printStackTrace(); 
       } catch (ExecutionException ee) { 
        ee.printStackTrace(); 
       } catch (InterruptedException ie) { 
        Thread.currentThread().interrupt(); // ignore/reset 
       } 
      } 
     }catch(Exception err){ 
      err.printStackTrace(); 
     } 
     System.out.println("Completed"); 
     service.shutdown(); 
    } 
    public static void main(String args[]){ 
     InvokeAllUsage demo = new InvokeAllUsage(); 
    } 
    class MyCallable implements Callable<Long>{ 
     Long id = 0L; 
     public MyCallable(Long val){ 
      this.id = val; 
     } 
     public Long call(){ 

      if (id % 5 == 0){ 
       id = id/0; 
      }   
      return id; 
     } 
    } 
} 

出力:

creating service 
Start 
future.isDone = true 
future: call =1 
future.isDone = true 
future: call =2 
future.isDone = true 
future: call =3 
future.isDone = true 
future: call =4 
future.isDone = true 
java.util.concurrent.ExecutionException: java.lang.ArithmeticException:/by zero 
     at java.util.concurrent.FutureTask.report(FutureTask.java:122) 
     at java.util.concurrent.FutureTask.get(FutureTask.java:188) 
     at InvokeAllUsage.<init>(InvokeAllUsage.java:20) 
     at InvokeAllUsage.main(InvokeAllUsage.java:37) 
Caused by: java.lang.ArithmeticException:/by zero 
     at InvokeAllUsage$MyCallable.call(InvokeAllUsage.java:47) 
     at InvokeAllUsage$MyCallable.call(InvokeAllUsage.java:39) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:262) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
     at java.lang.Thread.run(Thread.java:744) 
future.isDone = true 
future: call =6 
future.isDone = true 
future: call =7 
future.isDone = true 
future: call =8 
future.isDone = true 
future: call =9 
future.isDone = true 
java.util.concurrent.ExecutionException: java.lang.ArithmeticException:/by zero 
     at java.util.concurrent.FutureTask.report(FutureTask.java:122) 
     at java.util.concurrent.FutureTask.get(FutureTask.java:188) 
     at InvokeAllUsage.<init>(InvokeAllUsage.java:20) 
     at InvokeAllUsage.main(InvokeAllUsage.java:37) 
Caused by: java.lang.ArithmeticException:/by zero 
     at InvokeAllUsage$MyCallable.call(InvokeAllUsage.java:47) 
     at InvokeAllUsage$MyCallable.call(InvokeAllUsage.java:39) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:262) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
     at java.lang.Thread.run(Thread.java:744) 
Completed 
関連する問題