2009-07-19 27 views
4

Javaにスレッドプールを実装したいと思います。スレッドプールは、送信されたタスクの計算と入出力の動作に基づいて動的にサイズ変更できます。Javaでの適応スレッドプールの設計上の考慮

は実際に、私はC#でnew Thread Pool implementationと同じ動作を達成したい4.0

実装は既にありますか私は、主に既存の並行処理ユーティリティ(例えばCachedThreadPool)を使用してこの動作を達成することができますか?

C#バージョンは、最適な利用を実現するための自己計測を行います。どのような自己計器がJavaで利用可能であり、現在どのようなパフォーマンスの影響がありますか?

タスクが意図を伝える(例:I/O集中型の操作を入力し、CPU集中型の操作フェーズに入る)協調的アプローチを実行することは可能でしょうか?

ご提案は大歓迎です。コメントに基づいて

編集

対象のシナリオが考えられます

  • マルチWebサービスへのアクセスおよびアグリゲーション
  • をクロール

    • ローカルファイルが
    • をクロールし、処理
    • ウェブ

      キャッシュの問題dThreadPoolは、既存のスレッドがすべてブロックされたときに新しいスレッドを開始するということです。明示的な境界を設定する必要がありますが、それだけです。

      たとえば、私は100のWebサービスを連続してアクセスします。 100のCTPを作成すると、操作を実行するために100のスレッドが開始され、複数のI/O要求とデータ転送のトン数は確実にそれぞれの足でつまずくでしょう。静的なテストケースの場合、私は実験して最適なプールサイズを見つけることができますが、それを適応的に決定し、ある方法で適用したいと考えています。

    +0

    縮小するスレッドプールからどのようなメリットが得られるのかよくわかりません。何もしないスレッドのコストは事実上何もありません(おそらく、スレッドローカルキャッシュからの最大の影響です)。 –

    +0

    CachedThreadPoolのスレッドタイムアウトオプションと同じ利点があります。 – akarnokd

    +0

    キャッシュされたスレッドプールのようですか?デフォルトのアイドルタイムアウトは1分ですが、それを変更できます。 –

    答えて

    0

    代替アプローチを提示します。 1つのスレッドプールを持つことは素晴らしい抽象ですが、特にIOバインドが非常に高い場合はパフォーマンスがあまり良くありません。それを調整するには良い方法はありません。IOスループットを最大化するためにプールサイズを爆破したいのですが、あまりにも多くのスレッドスイッチなどから。

    代わりに私は、インスピレーションのためにApache MINAフレームワークのアーキテクチャを見てみることをお勧めします。 (http://mina.apache.org/)これは高性能のWebフレームワークです。サーバーフレームワークとして記述されていますが、スパイダリングやマルチサーバークライアントなどの逆シナリオでもうまく機能します。 (実際には、あなたのプロジェクトでそのまま使用することもできます。)

    すべてのIO操作にJava NIO(非ブロックI/O)ライブラリを使用し、小さくて速いソケットスレッドのセット、大きくて遅いビジネスロジックスレッドの2つのスレッドプールに分かれています。ネットワーク側の

    • 、NIOチャネルの大きなセット、それぞれのメッセージバッファ
    • チャンネルリストラウンドロビン通過ソケットスレッドの小さなプールに次のように層が見えます。彼らの唯一の仕事は、ソケットをチェックし、データをメッセージバッファーに移動し、メッセージが終了したらそれを閉じてジョブキューに転送することです。これらの人たちは高速です。なぜなら、彼らはちょうどビットをプッシュし、IO上でブロックされているすべてのソケットをスキップするからです。
    • すべてのメッセージをシリアライズする単一のジョブキュー
    • 処理スレッドの大きなプール。メッセージをキューから取り出し、解析し、必要な処理を行います。

    これは、IOが独自のレイヤーに分離され、IOスループットを最大限にするようにソケットスレッドプールを調整し、CPU /リソース使用率を制御するために処理スレッドプールを個別にチューニングすることができます。

    +0

    ありがとう、私はまもなくそれを見ます。 – akarnokd

    0

    プラットフォームごとにCPU使用率を監視する必要があると思います。あなたが持っているCPU /コアの数を調べ、負荷を監視してください。負荷が低く、さらに作業があることがわかったら、新しいスレッドを作成しますが、num-cpus(x = 2など)のx倍を超えないようにします。

    IOスレッドも実際に検討したい場合は、プールが使い果たされたときに各スレッドがどの状態にあるかを調べ、合計数から待機中のすべてのスレッドを差し引いてみてください。 1つのリスクは、あまりにも多くのタスクを許可してメモリを使い果たしてしまうことです。

    +0

    これは私の問題の1つだと思いますが、howtoはビジーとブロッキングの割合を(プラットフォームに依存しない方法で)スレッドごとに計測します。 – akarnokd

    +0

    私はあなたが楽器スレッドを提案するつもりはありませんでした。代わりに、OS APIを使用して、スレッドがスレッドの外部から待機しているかどうかを調べます。 –

    +0

    それは私が思う計装と呼ばれています。 – akarnokd

    1

    与えられた例では、1つのタスクが長い別の以上かかる場合、それは問題ではありませんので、すべての自由なコアにこれをparalellize、動的に分散作業負荷を持つ方法Javaでは

    Result[] a = new Result[N]; 
    for(int i=0;i<N;i++) { 
        a[i] = compute(i); 
    } 
    

    です。

    // defined earlier 
    int procs = Runtime.getRuntime().availableProcessors(); 
    ExecutorService service = Executors.newFixedThreadPool(proc); 
    
    // main loop. 
    Future<Result>[] f = new Future<Result>[N]; 
    for(int i = 0; i < N; i++) { 
        final int i2 = i; 
        a[i] = service.submit(new Callable<Result>() { 
         public Result call() { 
          return compute(i2); 
         } 
        } 
    } 
    Result[] a = new Result[N]; 
    for(int i = 0; i < N; i++) 
        a[i] = f[i].get(); 
    

    これは過去5年間でほとんど変更されていないため、最初は利用できなかったほどには涼しくありません。 Javaが本当に欠けているのはクロージャーです。実際に問題がある場合は、代わりにGroovyを使用することができます。

    追加:例としてではなく、パフォーマンスについて気にしていた場合、フィボナッチは、シングルスレッドで計算するとより速い関数の良い例であるため、並列に計算されます。

    1つの違いは、各スレッドプールには1つのキューしかないため、作業を盗む必要はないということです。これは、タスクごとにオーバーヘッドが増える可能性があることを意味します。ただし、タスクが通常約10マイクロ秒以上かかる場合は問題ありません。

    +0

    実際、あなたの答えは私の質問とは関係ありません。私は固定プールとキャッシュプールでそれを行う方法を知っていますが、CPU使用率、I/Oブロック、I/O転送プロパティを考慮し、最大CPUと最大Iを達成するためのものを 'スケジュール'/Oの利用を可能にする。 – akarnokd

    +0

    beforeTaskとafterTaskをオーバーライドするか、キューの長さとプール内のスレッド数を監視する別のスレッドを持つことで、これを行うことができます。しかし、これらのアプローチを試した後、使用可能なスレッドの数を増やして、OSスケジューラーがタスクを割り当てる最善の方法を考えさせてください(他のアプリケーション、CPU使用法、IO使用法などを知っているので) –

    +0

    要約すると、あなたが提案するものは、OSのスケジュールが行うように設計されており、Windows、Linux、Solaris上でうまく動作します。 OSスケジューラを信頼していない場合は、自分で作成しようとします。だから私の答えはあなたの質問に対する答えです。すなわち、それについて心配しないでください、OSは動作します! –

    2

    キーがボトルネックリソースであるマップを作成することを検討してください。

    プールに提出した各スレッドは、それがボトルネックだなリソースを提出する、すなわち「CPU」、「ネットワーク」、「C:\」あなたは、リソースごとに1つだけのスレッドを可能にすることにより開始することができますなど

    と仕事の完了率が上がらなくなるまでゆっくりと立ち上がります。 CPUのようなものは、コアカウントのフロアを持つことができます。

    +0

    このようなことを行う場合は、Mapの同期実装を使用してください。 –

    関連する問題