14

これは、スレッドの優先度に関するテストです。コードはThinkinginJavap.809からのものです

import java.util.concurrent.*;

public class SimplePriorities implements Runnable {
    private int countDown = 5;
    private volatile double d; // No optimization
    private int priority;

    public SimplePriorities(int priority) {
        this.priority = priority;
    }

    public String toString() {
        return Thread.currentThread() + ": " + countDown;
    }

    public void run() {
        Thread.currentThread().setPriority(priority);
        while (true) {
            // An expensive, interruptable operation:
            for (int i = 1; i < 10000000; i++) {
                d += (Math.PI + Math.E) / (double) i;
                if (i % 1000 == 0)
                    Thread.yield();
            }
            System.out.println(this);
            if (--countDown == 0)
                return;
        }
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++)
            exec.execute(new SimplePriorities(Thread.MIN_PRIORITY));
        exec.execute(new SimplePriorities(Thread.MAX_PRIORITY));
        exec.shutdown();
    }
}

次のような通常の結果が得られないのはなぜだろうか。

Thread[pool-1-thread-6,10,main]: 5 
Thread[pool-1-thread-6,10,main]: 4 
Thread[pool-1-thread-6,10,main]: 3 
Thread[pool-1-thread-6,10,main]: 2 
Thread[pool-1-thread-6,10,main]: 1 
Thread[pool-1-thread-3,1,main]: 5 
Thread[pool-1-thread-2,1,main]: 5 
Thread[pool-1-thread-1,1,main]: 5 
Thread[pool-1-thread-5,1,main]: 5 
Thread[pool-1-thread-4,1,main]: 5 
...

しかし、ランダムな結果(実行するたびに変化します):

Thread[pool-1-thread-2,1,main]: 5
Thread[pool-1-thread-3,1,main]: 5
Thread[pool-1-thread-4,1,main]: 5
Thread[pool-1-thread-2,1,main]: 4
Thread[pool-1-thread-3,1,main]: 4
Thread[pool-1-thread-1,1,main]: 5
Thread[pool-1-thread-6,10,main]: 5
Thread[pool-1-thread-5,1,main]: 5
...

Win764ビットJDK7でi3-2350M2C4TCPUを使用しています。重要ですか?

4

12 に答える 12

22

Javaスレッドの優先度は効果がありません

スレッドの優先順位はOS固有であり、多くのオペレーティングシステムではほとんど影響がありません。優先順位は、実行キューにのみ存在するスレッドを順序付けるのに役立ち、各スレッドで大量のCPUを実行しない限り、スレッドが主要な方法で実行される頻度は変更されません。

プログラムは多くのCPUを使用しているように見えますが、スレッドの数よりもコアの数が少ない場合を除いて、スレッドの優先順位を設定しても出力順序に変更がない場合があります。空きCPUがある場合は、優先度の低いスレッドでも実行がスケジュールされます。

また、スレッドが不足することはありません。優先度の低いスレッドでも、このような状況ではかなり頻繁に実行する時間が与えられます。優先度の高いスレッドには、より頻繁に実行するためにタイムスライスが与えられるはずですが、優先度の低いスレッドが終了するのを待ってから実行するという意味ではありません。

優先順位が1つのスレッドに他のスレッドよりも多くのCPUを与えるのに役立つ場合でも、スレッド化されたプログラムは、実行に大量のランダム性を注入するのに役立つ競合状態の影響を受けます。0ただし、表示されるはずのことは、最大優先度のスレッドが他のスレッドよりも頻繁にメッセージを吐き出す可能性が高いことです。に優先度を追加するとprintln()、それは何回もの実行で明らかになるはずです。

System.out.println(...)また、IOを書き込んでいるsynchronizedメソッドが、スレッドの相互作用やさまざまなスレッドが相互にブロックしている方法に劇的な影響を与えることに注意することも重要です。さらにThread.yield();、OSがスレッドのスケジューリングを行う方法によっては、何も実行されない場合があります。

しかし、ランダムな結果(実行するたびに変化します):

右。スレッド化されたプログラムからの出力は、定義上、スレッドが非同期で実行されているため、「完璧」になることはめったにありません。スレッドを互いに独立して並列に実行する必要があるため、出力をランダムにする必要があります。それが彼らの力です。正確な出力が必要な場合は、スレッドを使用しないでください。

于 2012-08-20T13:34:26.847 に答える
14

スレッドの優先順位は実装に依存します。特に、Windowsでは:

すべてのスレッドがCPUをめぐって競合している場合、スレッドの優先順位はあまり意味がありません。(出典

「JavaConcurrencyinPractice」という本も

スレッドの優先順位を使用する誘惑を避けてください。スレッドの優先順位はプラットフォームへの依存度を高め、活性の問題を引き起こす可能性があるためです。ほとんどの並行アプリケーションは、すべてのスレッドにデフォルトの優先順位を使用できます。

于 2012-08-20T13:34:50.200 に答える
12

スレッドの優先順位は実行順序を保証するものではありません。リソースが限られているときに機能します。システムがメモリまたはCPUのために制約に直面している場合、優先度の高いスレッドが最初に実行されます。十分なシステムリソースがあると仮定すると(単純なプログラムと投稿したシステムリソースの場合はそうなると思います)、システムの制約はありません。これが私が見つけたブログ投稿(私の投稿ではありません)で、それについての詳細情報を提供しています:スレッドの優先順位がめったに重要でない理由

于 2012-08-20T13:38:25.860 に答える
9

シンプルに保ち、ソースに直接行きましょう...

すべてのスレッドに優先順位があります。リソースを処理するための競合がある場合、通常、優先度の高いスレッドが優先度の低いスレッドよりも優先して実行されます。ただし、このような優先順位は、最も優先度の高いスレッドが常に実行されることを保証するものではなく、スレッドの優先順位を使用して相互排除を確実に実装することはできません。

  • Java言語仕様(第2版) p.445から。

また ...

スレッドの優先順位はJavaに存在し、多くの参照では、JVMは常にスケジューリングに最も優先度の高いスレッドの1つを選択すると述べていますが[52、56、89]、これは現在Java言語または仮想マシンの仕様によって保証されていません[53、90]。 。優先順位は、スケジューラーへのヒントにすぎません[127、227ページ]。

  • 並行Javaコンポーネントのテストから(PhD Thesis、2005) p。62。

  • 参照127、227ページ(上記の抜粋から)は、コンポーネントソフトウェア:オブジェクト指向プログラミングを超えて(C. Szyperskiによる)、Addison Wesley、1998年からのものです。

つまり、スレッドの優先順位に依存しないでください。

于 2013-08-19T10:42:36.923 に答える
5

スレッドの優先度は、OSタスクスケジューラへのヒントにすぎません。タスクスケジューラは、優先度の高いスレッドにのみより多くのリソースを割り当てようとしますが、明示的な保証はありません。

実際、これはJavaやJVMに関連するだけではありません。ほとんどの非リアルタイムOSは、示唆的な方法でのみスレッドの優先順位(管理対象または非管理対象)を使用します。

Jeff Atwoodは、このトピックに関する優れた投稿をしています。「スレッドの優先順位は悪です

ここに問題があります。誰かが優先度の低いスレッド(プロデューサー)で「cond」を真にする作業を開始し、プログラムのタイミングが、このスピニングを発行する優先度の高いスレッド(コンシューマー)がスケジュールされるようになっている場合、コンシューマーはプロデューサーを完全に飢えさせます。これは古典的なレースです。また、明示的なスリープが存在する場合でも、スリープを発行すると、優先度が低いため、プロデューサーをスケジュールできません。コンシューマーは永遠にスピンし、空きCPUが開かない限り、プロデューサーは決して生産しません。おっと!

于 2012-08-20T13:34:38.083 に答える
4

他の回答で述べられているように、スレッドの優先順位は、厳密なルールの定義よりもヒントです。

とはいえ、優先順位が厳密に考慮されたとしても、テストのセットアップでは、「期待される」と説明する結果は得られません。最初に、優先度が同じように低い5つのスレッドと、優先度が高い1つのスレッドを作成します。

  • 使用しているCPU(i3)には4つのネイティブスレッドがあります。したがって、優先度が高いとスレッドが中断せずに実行されることを意味する場合でも(これは正しくありません)、優先度の低いスレッドはCPUパワーの3/4を取得します(他のタスクが実行されていない場合)。このCPUパワーは5つのスレッドに割り当てられるため、優先度の低いスレッドは、優先度の高いスレッドの4 * 3/4 * 1/5=3/5倍の速度で実行されます。高優先度スレッドが完了した後、低優先度スレッドは高優先度スレッドの4/5の速度で実行されます。

  • 優先度の高いスレッドの前に優先度の低いスレッドを起動しています。したがって、それらは少し早く開始します。ほとんどのシステムでは、「優先順位」はナノ秒まで実装されていないと思います。したがって、OSは、スレッドが別のスレッドに切り替わるまで「少し長く」実行できるようにします(切り替えコストの影響を減らすため)。したがって、結果は、そのスイッチングがどのように実装され、タスクがどれだけ大きいかに大きく依存します。タスクが小さい場合は、切り替えが行われない可能性があります。この例では、優先度の低いすべてのスレッドが最初に終了します。

  • これらの計算では、極端なケースとして解釈される場合、優先度の高低を想定しています。実際、優先度は、変数nとmを使用した「m個のケースのうちn個がこれを好む」のようなものです。

  • コードにThread.yieldがあります!これにより、実行が別のスレッドに渡されます。これを頻繁に行うと、すべてのスレッドのCPUパワーが等しくなります。

したがって、あなたが質問で言及した出力、つまり、優先度の高いスレッドが最初に終了し、次に優先度の低いスレッドが終了することは期待していません。

確かに:Thread.yieldという行を使用すると、各スレッドが同じCPU時間を取得するという結果が得られます。Thread.yieldという行がなく、計算数を10倍に増やし、低prioスレッドの数を10倍に増やすと、期待される結果が得られます。つまり、高prioスレッドが何らかの係数で早く終了します(ネイティブCPUスレッドの数によって異なります)。

于 2013-08-19T07:13:34.173 に答える
1

スレッドの優先度は、CPUが100%の場合に、OSが一部のスレッドを他のスレッドよりも優先することを認識できるようにするためのヒントです(無視できます)。スレッドの優先順位は、スレッドを開始する前に設定する必要があります。そうしないと、無視できます。

Windowsでは、スレッドの優先度を設定するには管理者である必要があります。

于 2012-08-20T19:27:42.953 に答える
1

OSはJavaスレッドの優先順位を自由に無視できると思います。

于 2012-08-20T13:32:25.130 に答える
1

考慮すべきいくつかの事柄:

于 2013-08-19T07:27:52.810 に答える
0

一部のOSは、スレッドの優先順位を適切にサポートしていません。

于 2016-03-30T04:08:44.877 に答える
0

OSが異なればスレッドの優先順位も異なることを理解する必要があります。たとえば、Windowsはプリエンプティブタイムスライスベースのスケジューラを使用します。これにより、優先度の高いスレッドに大きなタイムスライスが与えられますが、他のOS(非常に古いもの)では、優先度の高いスレッドが優先度の低いスレッドの前に完全に実行される非プリエンプティブスケジューラが使用されます。優先度の高いスレッドがスリープ状態になるか、IO操作などを実行しない限り。

そのため、優先度の高いスレッドが完全に実行されるとは限りません。実際には、優先度の低いスレッドよりも長時間実行されるため、出力はこのように順序付けられます。

Windowsがマルチスレッドを処理する方法を知るには、以下のリンクを参照してください。

https://docs.microsoft.com/en-us/windows/win32/procthread/multitasking

于 2019-09-28T19:34:02.753 に答える
0

優先度の高いスレッドは、優先度の低いスレッドが完了するまで停止しません。優先度が高いからといって、何かが速くなるわけではありません。もしそうなら、私たちは常にすべてを優先度の高いものにします。また、優先度が低いからといって、処理が遅くなったり、使用したりすることはありません。

私が理解しているように、システムの残りの部分はアイドル状態にして、システムの残りの容量が無駄になっている間、最も優先度の高いスレッドを機能させる必要があると誤解しています。

于 2020-02-16T14:55:48.140 に答える