0

Javaでスレッドを使用してアプリケーションを作成していますが、ループ内のスレッド数を一定に保つことに問題があります(新しいスレッドが新しいデータで着信します)。ExecutorServiceを使用してスレッドの数を制限していますが、新しいスレッドを開始する際に問題が発生します。

私はそのようなものを持っています:

ExecutorService execDownload = Executors.newFixedThreadPool(5);
UniqList<String> documentList = new UniqList<String>("startfile.txt");
        Future<UniqList<String>> future;
        while( !execDownload.isShutdown()) {
            future = execDownload.submit(new Parser(documentList.get(i)));
            i++;
            try {
                documentList.addAll(future.get());
            } catch (InterruptedException | ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

パーサーは、UniqListを返す呼び出し可能オブジェクトです。このリストの要素を、すべてのドキュメント名のコレクションであるグローバルリストに追加します。問題は、一定数のパーサーを同時に実行したいということです。プログラムを開始する前にドキュメントのすべての名前を知っているとしたら、それは簡単です。ExecutorServicesubmit()メソッドを呼び出す必要があるからです。つまり、100個のファイル名がある場合は100回呼び出す必要がありますが、ドキュメントのすべての名前(名前)はわかりません。このコードを呼び出すことによって解析されます:

new Parser(documentList.get(i))

名前はファイル内にあります。では、もう一度質問します。新しいデータが到着したときに、スレッドの数を一定に保つにはどうすればよいでしょうか。上記のコードでは、Futureオブジェクトが1つしかなく、それが私の最大の問題だと思います。Futureの配列を作成する必要がありますか?しかし、ExecutorServiceからのスレッドが新しいデータを返したときを検出する方法...

アルゴは(私が思うに)あるべきです:

  1. 初期パラメータ(最初のドキュメント名)でプログラムを起動します
  2. リストアイテム
  3. ExecutorServiceに送信してParserクラスを開始し、開始ファイルからすべてのドキュメント名を抽出します
  4. #2のドキュメント名をグローバルドキュメント名リストに追加する
  5. 別のスレッドを作成し、グローバルドキュメント名リストの名前でドキュメントを解析します。スレッドの最大数を開始します(ExecutorServiceによって制限されます)。次のすべてのファイルを解析し、それらから新しいファイル名を抽出します
  6. #3からグローバルドキュメント名に名前を追加しますリストを#4に戻します

ご覧のとおり、再帰のようなものです。ウェブサイト、1つの開始ノード、第1レベルのカテゴリ、第2レベルの記事などを解析するのと同じ問題だと思います。

リンク、またはサンプルコードは本当に便利です。ありがとうございました。

4

2 に答える 2

0

コードはほぼシーケンシャルです。future.get()はタスクが完了するまでブロックするため、前のタスクが実行されている限り、新しいタスクを送信することはできません。次のいずれかを実行できます。

  • N個のタスクをループで送信し、先物を保存します。次に、先物の場合はget onを呼び出して、新しいタスクを送信します。
  • しかし、それは車輪の再発明になります。CompletionServiceは、まさに必要なことを実行しているようです。
于 2012-12-20T19:12:53.520 に答える
0

未来を捨てて、エグゼキューターについて知るためにパーサーを構築することをお勧めします。

execDownload.submit(new Parser(execDownload, documentList.get(i)));

この "execDownload" ExecutorService をメンバー変数としてパーサーに格納します。

Parser.run() の最後で、新しく解析されたドキュメント名のリストを取得したら、それらの新しいパーサーを作成し、それらもスケジュールします。

foreach (String newDoc: UniqList)
{
     execDownload.submit(new Parser(execDownload, newDoc));
}
于 2012-12-20T19:15:38.870 に答える