1

方法Thread.yield

現在実行中のスレッドオブジェクトを一時的に一時停止し、他のスレッドの実行を許可します。

したがって、次のコードでは:

public class Test implements Runnable {  

    private int stopValue;  

    public Fib(int stopValue){  
        this.stopValue = stopValue;  
    }  

    @Override  
    public void run() {  

        System.out.println("In test thread");  
        for(int i = 0; i < stopValue; i++){  
            c = i + 1;  
        }  

        System.out.println("Result = "+c);        
    }  

    public static void main(String[] args){  
        int defaultStop = 1024;  
        if(args.length > 0){   
            defaultStop = Integer.parseInt(args[0]);  
        }  
        Thread a = new Thread(new Fib(defaultStop));  
        System.out.println("In main");  
        a.setDaemon(true);  
        a.start();  
        Thread.yield();       
        System.out.println("Back in main");  
    }  

}

私は私が見るべきだと期待しています:

  1. In main それから
  2. In test thread

残りは未定義になります。しかし、なぜ時々私が見るだけなのか理解できません: In mainそしてスレッドBack in mainからの印刷ステートメントはありませんか?Test

4

5 に答える 5

4

yield()は、スケジュールされたOSへのヒントですが、スケジュールに関しては何の保証も提供しません。常に非常に長く一時停止するとは限りません。繰り返し呼び出すと、数マイクロ秒しかかからない場合があります。

スレッドの開始には時間がかかり、メインスレッドが一時停止しても、バックグラウンドスレッドが開始する前に終了する場合があります。


ご覧のとおり、yield()は非常に短時間一時停止します。

long start = System.nanoTime();
long runs = 20000000;
for (int i = 0; i < runs; i++)
    Thread.yield();
long time = System.nanoTime() - start;
System.out.printf("Thread.yield() took an average of %,d ns.%n", time / runs);

プリント

Thread.yield() took an average of 148 ns.

比較すると、System.nanoTimeは私のマシンでは時間がかかります。

long start = System.nanoTime();
long runs = 20000000;
for (int i = 0; i < runs; i++)
    System.nanoTime();
long time = System.nanoTime() - start;
System.out.printf("System.nanoTime() took an average of %,d ns.%n", time / runs);

プリント

System.nanoTime() took an average of 656 ns.

どちらの時間もOSごとに、またマシンごとに異なります。

于 2012-07-19T06:52:12.243 に答える
2

準備ができているスレッドのセットがコアの数より少ないため、yield()はおそらく何もしません。この場合、両方のスレッドはとにかく実行でき、main()は実行中のコアに対して実行を継続します。 OSは、別のCPUコアで新しいスレッドを実行するためのコア間ドライバーの呼び出しを発行します(キューが発生する可能性が非常に高い)。次に、「System.out.println」との相互作用があります。これは、おそらくミューテックスで保護されている出力ストリーム呼び出しです。

異なる環境/CPU/ OSでyield()が実際に何をするのかについて、理解できる説明をすぐに見つけることができません。これは、私がこれを使用したことがない理由の1つです。もう1つは、どのように機能しても、その用途は考えられないということです。

于 2012-07-19T07:28:22.243 に答える
0

スレッドが開始する前に、メインプロセスが終了した可能性があります。Thread.yield()特定の時間にスレッドを強制的に実行するという保証はありません。スレッドが開始されなかった場合、はsetDaemon()効果がありません。

于 2012-07-19T06:52:28.190 に答える
0

Thread.yield()を次のように置き換えてみてください。

try {
        Thread.sleep(500);
    } catch (InterruptedException ex) {
        System.out.println(ex);
    }
于 2012-07-19T07:29:00.113 に答える
0

@Peterの答えは良いものですが、答えとしていくつかの追加情報を追加したいと思いました。

まず、他の場所で述べたようにa.setDaemon(true)、JVMは終了する前に終了するのを待たないようにします。Thread aあなたの本当の質問が、JVMがシャットダウンする前にThread aそれが機能することを確認する方法である場合は、を削除することが解決策になる可能性があります。JVMが終了すると、デーモンスレッドを強制終了できます。デーモン以外のスレッドが待機されます。そのため、メソッドが戻ってメインスレッドが終了する可能性がありますが、それでも実行は完了します。setDaemon(true)main()Thread a

おっしゃるThread.yield()ように、javadocsの状態は次のとおりです。

現在実行中のスレッドオブジェクトを一時的に一時停止し、他のスレッドの実行を許可します。

ただし、これは多少誤解を招く可能性があります。たとえば、アーキテクチャ上で2つのスレッドを実行し、2つ以上のプロセッサを使用している場合、yield()事実上何も実行されません。実行キューにはプロセッサリソースを待機している他のスレッドがないため、メインスレッドはすぐに再スケジュールされ、最小限の一時停止で実行を継続します。

単一のCPUシステムで実行していて、実行している場合でも、IOMainである実行を実行しyield()ます。IOがブロックされ、スレッドの実行がすぐに元に戻る場合があります。Thread aSystem.outMain

結局のところ、非常にユニークな状況でのみ、必要な使用がyield()必要です。私は多くのマルチスレッドプログラミングを行ったことがあり、それを使用したことはありません。プロファイラーの出力や反対の専門家のアドバイスがない限り、JVMスレッドスケジューリングがタイムスライスの観点から「正しいことを行う」ことを信頼することを常にお勧めします。

于 2012-07-19T14:20:19.097 に答える