1

作業 ( Runnable ) を並行して実行する 12 個のスレッドのセットがあります。基本的に、各スレッドは次のことを行います。

Runnable r;

while (true) {
    synchronized (work) {
        while (work.isEmpty()) {
            work.wait();
        }
        r = work.removeFirst();
    }
    r.execute();
}

次のように作業が追加されます。

Runnable r = ...;

synchronized (work) {
    work.add(r);
    work.notify();
}

新しい作品が利用可能になると、リストに追加され、ロックが通知されます。待機しているスレッドがあれば、それが起床されるので、この作業を実行できます。

ここに問題があります。スレッドが起動されると、別のスレッドがこの作業を実行する可能性が非常に高くなります。これは、後者のスレッドが前の作業を完了し、while(true)ループに再び入るときに発生します。ワーク アクションが小さい/短いほど、これが発生する可能性が高くなります。

これは、スレッドを無料で起動していることを意味します。高いスループットが必要なため、この動作はパフォーマンスを低下させると思います。

これをどのように解決しますか?理論的には、保留中のスレッド ウェイクアップ通知をキャンセルできるメカニズムが必要です。もちろん、これはJavaでは不可能です。

スレッドごとにワークリストを導入しようと考えました。作業を 1 つのリストにプッシュする代わりに、作業は 12 の作業リストに分散されます。しかし、これは他の問題を引き起こすと私は信じています。たとえば、あるスレッドには多くの保留中の作業があり、別のスレッドには保留中の作業がない場合があります。本質的に、事前に特定のスレッドに作業を割り当てるソリューションは非常に複雑になる可能性があり、最適ではないと考えています。

ありがとう!

4

2 に答える 2

2

あなたがしているのはスレッドプーリングです。java-5 より前の同時実行フレームワークである PooledExecutor クラスを参照してください: http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html

于 2013-04-06T16:55:10.833 に答える
0

私の以前の回答に加えて、別の解決策です。この質問は私に興味をそそります。

ここでは、volatile ブール値でチェックを追加しました。

無駄にスレッドをウェイクアップする状況を完全に回避するわけではありませんが、回避するのに役立ちます。実際、「100ミリ秒後にジョブが完了する可能性が高いことがわかっている」などの追加の制限なしに、これを完全に回避する方法はわかりません。

volatile boolean free = false;

while (true) {
    synchronized (work) {
        free = false;               // new rev.2
        while (work.isEmpty()) {
            work.wait();
        }
        r = work.removeFirst();
    }
    r.execute();
    free = true;        // new
}

--

synchronized (work) {
    work.add(r);
    if (!free) {         // new
         work.notify();
    }                    // new
    free = false;        // new rev.2
}
于 2013-04-06T17:38:23.503 に答える