4

私が投稿した私の以前の質問について:

いくつかの非常に大きなtxtファイルを読み取る必要があり、ユーザーの入力に応じて、複数のスレッドまたは単一のスレッドを使用する必要があります。ユーザー入力を取得するメイン メソッドがあり、ユーザーが 1 つのスレッドを要求し、そのスレッドの 20 個の txt ファイルを処理したいとします。どうすればこれを達成できますか? 以下は私のコードやその設定ではなく、単なる「アイデア」であることに注意してください。

例:

int numFiles = 20;
int threads = 1;

 String[] list = new String[20];
 for(int i = 1; i < 21; i++){
   list[i] = "hello" + i + ".txt";//so the list is a hello1.txt, hello2.txt, ...,  hello20.txt
 }

 public void run(){
 //processes txt file
 }

要約すると、単一のスレッドでこれを達成するにはどうすればよいでしょうか? 20スレッドで?

そして、ユーザーはthreadPoolsの使用を提案しました:

ユーザーが使用するスレッド数を指定したら、プールを適切に構成し、一連のファイル読み取りジョブを送信して、プールに実行を分類させます。Java の世界では、Executors.newFixedThreadPool ファクトリ メソッドを使用し、各ジョブを Callable として送信します。Java スレッド プーリングに関する IBM の記事を次に示します。

これで、txt ファイル名を取り込んで処理を行う sortAndMap(String x) というメソッドができました。上記の例では、次のようになります。

Executors.newFixedThreadPool(numThreads);

上記の例が実行可能になるように、これを threadPools で使用するにはどうすればよいですか?

4

3 に答える 3

12

わかりました、いくつか説明する必要があるので、これについてはご容赦ください。

まず、複数のディスクまたは SSD である単一のディスクがない限り、ディスクから読み取るために複数のスレッドを使用することはお勧めしません。このトピックに関する多くの質問が投稿されましたが、結論は同じでした: 複数のスレッドを使用して単一の機械的ディスクから読み取ると、パフォーマンスが向上するどころか低下します。

上記は、ディスクの機械的ヘッドが次の読み取り位置を探し続ける必要があるために発生します。複数のスレッドを使用すると、各スレッドが実行される機会が得られると、ヘッドがディスクの別のセクションに向けられるため、ディスク領域間で非効率的にバウンスすることになります。

複数のファイルを処理するために受け入れられている解決策は、単一のプロデューサー (リーダー スレッド) と複数のコンシューマー (処理スレッド) のシステムを持つことです。この場合の理想的なメカニズムはスレッド プールです。スレッドはプロデューサーとして機能し、ワーカーが処理するタスクをプール キューに入れます。

このようなもの:

int numFiles = 20;
int threads = 4;

ExecutorService exec = Executors.newFixedThreadPool(threads);

for(int i = 0; i < numFiles; i++){
    String[] fileContents = // read current file;
    exec.submit(new ThreadTask(fileContents));
}

exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
...

class ThreadTask implements Runnable {

   private String[] fileContents;

   public ThreadTask(String[] fileContents) {
        this.fileContents = fileContents;
   }

   public void run(){
      //processes txt file
   }
}
于 2012-05-01T11:43:57.657 に答える
1

高レベルの並行性に関するこのチュートリアルを読むことから始めます。マルチスレッドは初めてのように思われるので、同時実行チュートリアル全体を読むことをお勧めします。

于 2012-05-01T11:42:34.553 に答える
1

したがって、newFixedThreadPool()呼び出しはExecutorServiceのインスタンスを返します。JavaDoc を参照できます。これは非常に包括的で、実行可能な例が含まれています。ファイル処理タスクを実装する のいずれかsubmitまたはinvokeAll複数のを使用すると、見返りに の数が得られます。それらのメソッドは、完了時にタスク実行の結果を提供します (その部分を自分で作成する必要があります:))CallableFutureget()

于 2012-05-01T11:43:34.717 に答える