2

私はこの次の問題で立ち往生しています。たとえば、1000個のアイテムがあるリクエストがあり、これを解決するためにJavaExecutorを利用したいとします。

これが主な方法です

public static void main(String[] args) {

     //Assume that I have request object that contain arrayList of names
     //and VectorList is container for each request result

     ExecutorService threadExecutor = Executors.newFixedThreadPool(3);
     Vector<Result> vectorList = new Vector<Result();

     for (int i=0;i<request.size();i++) {
          threadExecutor.execute(new QueryTask(request.get(i).getNames, vectorList)
     }

      threadExecutor.shutdown();

      response.setResult(vectorList)

}

そしてこれがQueryTaskクラスです

public QueryTask() implements Runnable {

    private String names;
    private Vector<Result> vectorList;

    public QueryTask(String names, Vector<Result> vectorList) {
          this.names = names;
          this.vectorList = vectorList;
    }

    public void run() {
         // do something with names, for example, query database
         Result result = process names;

         //add result to vectorList
         vectorList.add(result);
    }


}

したがって、上記の例に基づいて、リクエストに含まれるデータごとにスレッドプールを作成し、それを同時に実行して、結果をVectorListに追加します。そして、プロセスの最後に、すべての結果をベクターリストに入れておきたいと思います。

応答に一貫性のない結果が出続けます。たとえば、10個の名前でリクエストを渡すと、3個または4個しか返されません。場合によっては、応答に何も返されません。私は10を通過すると、10を取り戻すことを期待していました。

誰かが問題の原因を知っていますか?

どんな助けでもそれを高く評価するでしょう。

ありがとう

4

3 に答える 3

3

簡単な解決策は、ExecutorService.awaitTermination()への呼び出しを追加することです。

public static void main(String[] args) {

     //Assume that I have request object that contain arrayList of names
     //and VectorList is container for each request result

     ExecutorService threadExecutor = Executors.newFixedThreadPool(3);
     Vector<Result> vectorList = new Vector<Result();

     for (int i=0;i<request.size();i++) {
          threadExecutor.execute(new QueryTask(request.get(i).getNames, vectorList)
     }

      threadExecutor.shutdown();
      threadExecutor.awaitTermination(aReallyLongTime,TimeUnit.SECONDS);

      response.setResult(vectorList)

}
于 2010-10-21T23:50:02.503 に答える
2

に置き換える必要がありthreadExecutor.shutdown();ますthreadExecutor.awaitTermination();を呼び出した後、呼び出すthreadExecutor.shutdown()必要があります。前者は単にシャットダウンを開始する非ブロッキング呼び出しですが、後者は実際にすべてのタスクが終了するのを待つブロッキング呼び出しです。前者を使用しているため、すべてのタスクが完了する前に戻ってくる可能性があります。そのため、常にすべての結果が返されるとは限りません。Java APIはあまり明確ではないため、誰かがこれについてバグを報告しました。threadExecutor.awaitTermination()

于 2010-10-21T22:17:44.907 に答える
0

ここには少なくとも2つの問題があります。

  1. メインでは、ExecutorServiceをシャットダウンしてから、すぐに結果を取得しようとします。エグゼキュータサービスはジョブを非同期的に実行するため、すべてのジョブがまだ完了していない可能性が非常に高くなります。response.setResult(vectorList)を呼び出すと、vectorListが完全に入力されません。

2.すべてのランナブル内から同じVectorオブジェクトに同時にアクセスしています。これによりConcurrentModificationExceptions、ベクター内に、または単にクローバーが発生する可能性があります。QueryTask内のベクターで手動で同期するか、代わりにスレッドセーフなコンテナーを渡す必要があります。Collections.synchronizedList( new ArrayList() );

于 2010-10-21T22:14:50.797 に答える