0

私は次のコードを持っています:

public class Test {
   List<Future> future = new ArrayList<Future>();

   public static void main(String args[]) throws Exception {

     Adapter b1 = new Adapter();
     final ExecutorService threadPool = Executors.newCachedThreadPool();

      for(//iterate for number of files) {  
         while(data exists in file) {
            //Call a function to process and update values in db 
            future.add(threadPool.submit(new Xyz(b1)));
            //read next set of data in file;
         }
       }

      try {
         for(Future f: future) { 
            f.get(); 
         }
      }
      catch(Exception e) {
         throw e;
      }    
   }
}

class Xyz implements Runnable {
   private Adapter a1;

   public Xyz(Adapter al) {
      this.a1=a1;
   }

   @Override
   public void run() {
      try { 
         a1.abc();
      } catch (Exception e) {
          throw new RuntimeException(e);
      } 
   }
}

ファイル数が1の場合(forループは1回実行されます)、コードは正常に実行されます。

ただし、ファイルの数が増えると、コードがメソッドから戻ることはありませんfuture.get()

4

2 に答える 2

1

好奇心から..どこかでエグゼキュータをシャットダウンする必要がありますか?

はい、これが問題である可能性があります。Future.get()対応するタスクが完了するまでそれぞれがブロックされ、すべてのタスクが完了するとmainスレッドが終了します。ただし、スレッドプールスレッドはバックグラウンドでアクティブなままであるため、Javaプロセスは終了しません。エグゼキュータを使い終わったら、おそらくmainメソッドの最後のこととして、エグゼキュータをシャットダウンする必要があります。

また、同じ Adapterインスタンスをラップし、すべてがそのメソッドを呼び出す多くのタスクを送信していることにも注意してくださいabc()。複数のスレッドで同時に呼び出されたときにデッドロックするものがないことを確認してください。

于 2012-12-20T12:30:57.793 に答える
0

あなたのCallable::call/Runable::runは戻りません。そうでなければ、対応する未来はブロックされません。

追加のexecutor.shutdownfuture.cancelは、InterruptedException送信したオブジェクトのスレッド処理を停止する方法ですが、それをキャッチするかどうかはあなた次第です。あなたはあなたが提出した仕事を止める責任があります。

何千ものCallables/Runnablesをに送信すると、CachedExecutor非常に多くのスレッドが生成されるため、マシンが非常に遅くなり、永遠にかかると思われる可能性があります。しかし、あなたはそれに気づいたでしょう。

未定義の数の並列化可能なタスクを処理するときFixedThreadPoolは、CPUコアがあるスレッドよりも多くないスレッドを使用することをお勧めします。

編集:したがって、ブレークポイントをに設定してa1.abc();前に進むと、おそらくそれが戻らないことがわかります。

于 2012-12-20T13:02:47.437 に答える