2011-03-31 21 views
3

私は既存のJavaアプリケーションの拡張に取り組んでいます。このアプリケーションは、毎日数百万のメッセージを処理するメッセージプロセッサです。基本的にスレッドとキューを持つCore Javaを使用して記述され、Collectionクラスを使用して実装されます。ThreadPoolExecutorスレッドは他のスレッドと競合しています

このアプリケーションでは、いくつかの種類のメッセージが1つのスレッドで実行されています。私はデュアルプロセッサーを持っているので、アプリケーションのこの特定の部分をマルチスレッドにして、メッセージをより速く処理する作業を与えられました。

Java 5を使用しているので、私はThreadPoolExcecutorを使用してアプローチしました。特定のスレッドのメッセージを独自のスレッドで処理できるように、クライアントごとにプロセッサスレッドを作成しました。プロセッサスレッドはCallableインターフェイスを実装しています。これにより、前のタスクが終了したかどうかを将来のオブジェクトで確認できます。

初期化処理中に、すべてのクライアントを調べ、それぞれのプロセッサスレッドを作成し、そのIDを固有のキーとしてマップに格納します。以前に提出されたジョブを追跡するために、同じIDをユニークキーとして使用して、別のマップに将来のオブジェクトを再度保持します。

以下

私が使用したコードの一部抜粋です:メインクラスでは - 上記の実装は私に良い取り組んでいる

ThreadPoolExecutor threadPool = null; 
int poolSize = 20; 
int maxPoolSize = 50; 
long keepAliveTime = 10; 
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(1000); 
threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize,keepAliveTime, TimeUnit.SECONDS, queue); 

    .... 
    .... 
for (each client...) { 
    id = getId().. 
    future = futuremap.get(id); 
    if(!future.isDone()) 
     continue; 
    if(future == null || future.isDone()) { 
     processor = processormap.get(id); 
     if(processor == null) { 
     processor = new Processor(.....); 
     //add to the map 
     processormap.put(id,processor); 
     } 
     //submit the processor 
     future = threadPool.submit(processor); 
     futuremap.put(id,future); 
} 
} 

プロセッサスレッド

public class MyProcessor implements Callable<String> { 
     ..... 
     ..... 
    public String call() { 
     .... 
     .... 
    } 
} 

問題

テスト環境。しかし、本番環境(編集#1 - Ubuntu 、Linux Slackware、Java - 1.6.0_18)では、この新しいThreadpoolExecutorで管理されていない他のスレッドが影響を受けていることがわかりました。すなわち、それらのタスクは何時間も遅延している。これは、ThreadPoolExecutorsによって作成されたスレッドが、すべてのリソースを取得していて、他のスレッドにチャンスを与えていないためですか?

ThreadPoolExceutorを使用して作成された新しいスレッドは独立したタスクを実行しており、リソースの他のスレッドと競合しません。競合状態のシナリオは存在しない。

新しいスレッドについては、最大20スレッド(corepoolsize)が実行され、拒否例外はないことがわかります。つまり、サブミット数がキューの境界内にあります。

これは何が起こっているのですか?

ありがとうございます。

+0

アプリケーション内の任意の場所でスレッド優先度を(プールなどから)変更しますか?これは、異なるプラットフォームに異なる効果をもたらす可能性があります。 – Nr9

+0

いいえスレッドに明示的に優先順位は設定されていません。 – Chandra

+0

あなたはどんなjvmを実行していますか? –

答えて

0

以前のLinuxスレッドの経験では、同じ負荷のもとで同じシステムを実行しているシステムと比べて、非常にビジー状態のときにスレッドスターベーションが発生する可能性がはっきりとわかりました。標準的な待機/通知プリミティブ(IIRC)を使用すると、CPUの負荷が重い場合、いくつかのスレッドが他のCPUよりもはるかに多くのCPU時間を要することを示すテストプログラムを作成しました。私の解決策は、公正なモードでリエントラントロックを使用してラウンドロビンを行うことでした。

また、IIRCは、各作業イベントの終了時にThread.yieldを投げても効果がありませんでした。

このすべては、Linuxディストリビューションが使用しているいくつかのスレッドライブラリのどれが重要な影響を受ける可能性があります。

作業負荷を支配する作業キューにスローラを追加することで、多少の改善が得られるかもしれませんが、他の無関係なスレッドで保留中の作業量に何らかの形で適応していれば最適です。

関連する問題