2012-03-16 15 views
0

Thread.yield()メソッドに関するいくつかの質問。私が理解していることは、Thread.Yield()を呼び出すと、現在実行中のスレッドは実行可能状態に戻ります。スレッドの優先順位に依存するスレッドスケジューラは、次に優先度の高いスレッドを実行します。今私は1つのサンプルプログラムを持っています。下記を参照してください。yieldに関する疑問()

package thread; 

public class YieldTest implements Runnable { 

    @Override 
    public synchronized void run() { 
     System.out.println(Thread.currentThread().getName()+", executing.."); 
     for(int i = 0 ; i <5;i++){ 
      if(i==2){    
       Thread.yield(); 
       System.out.println(Thread.currentThread().getName()+": "+i+" yielded()"); 
       /*try { 
        Thread.sleep(1000); 
        System.out.println(Thread.currentThread().getName()+": "+i+" yielded()"); 
       } catch (InterruptedException e) { 

        e.printStackTrace(); 
       }*/ 

      }else{ 
       System.out.println(Thread.currentThread().getName()+": "+i); 
      } 

     }  
    } 


public static void main(String[] args) { 

    YieldTest test = new YieldTest(); 
     Thread t1 = new Thread(test); 
     t1.setName("A"); 
     t1.setPriority(9); 
     Thread t2 = new Thread(test); 
     t2.setName("B"); 
     Thread t3 = new Thread(test); 
     t3.setName("C"); 

     t2.setPriority(6); 
     t2.setPriority(4); 

     t1.start(); 
     t2.start(); 
     t3.start(); 

    } 


} 

ここで私は、次のように常に

A, executing.. 
A: 0 
A: 1 
A: 2 yielded() 
A: 3 
A: 4 
C, executing.. 
C: 0 
C: 1 
C: 2 yielded() 
C: 3 
C: 4 
B, executing.. 
B: 0 
B: 1 
B: 2 yielded() 
B: 3 
B: 4 

を出力を取得しています今の質問は、収率(ある)メソッドは、バックrunable状態に行く必要があり、他のスレッドが実行する必要があります。 0 A:1 A:そう出力.. A実行し、次のよう

Aのようなものでなければならない0 C:2 .. Cを実行する()

Cを得1個の C:2が得られた()

A: 3 
A: 4 

B、実行.. B:0 B:1 B:2が得られた()

C: 3 
C: 4 

B: 3 
B: 4 

また、スレッドの優先順位はどうですか。なぜ私たちはスレッドの優先順位が必要なのか保証されていませんか?私が間違っている場合は私を修正してください。

+0

あなたは本当に解決しようとしている問題は何ですか?おそらく 'yield()'を呼び出すことは最良の解決策ではありません。 –

+0

'yield()'の詳細については、[この質問](http://stackoverflow.com/questions/5156985/how-does-method-yield-work)を参照してください。 – Pops

+0

この特定のシナリオでは、スレッドAがBの前に完了しても起動する時間があっても、私は驚くことはありません。 – pap

答えて

2

実行メソッドはすべて同じオブジェクト(テスト)で同期されています。したがって、最初のスレッドのrunメソッドが終了するまで他の誰もrun()メソッドに入ることができないため、何も得られません。

基本的にスレッド1が起動し、run()メソッドに入ります。これは 'this'で同期されます。 2つの数字を出力した後、結果が得られます。しかし、スレッド2とスレッド3は両方ともrunメソッドに入るのを待っています。なぜなら、それらはテスト時にモニターを取得できないからです。だから利回りは何もしません。スレッド1が終了すると、同じ問題が発生します。

+0

よろしくお願いします。同期化されていない場合は、そのようにして1つのスレッドの後にoeスレッドのようなプロパティ結果を得ることはできません。 – user414967

1

スレッドの優先順位は保証されていません。これはJVMへの示唆に過ぎず、JVMは実際に実行するスレッドを決定する際に他の要素を調べることができます。技術的には、JVMは望むならランダムに選択することもでき、それでもthe JVM specificationに準拠することができます。

2

Javaがグリーン・スレッディングを使用していたとき、歩留まりが向上しました。今度はOSに通知する一方、スレッドは待機状態(実行不可)に置くことができます。しかし、スレッドが実際に別のスレッドを実行できるようにするかどうかは、OSとJVMによって異なります。それはあなたのコントロールから外れています。

しかし、最終的に私は今までに何も歩留まりを使用したことはありません。あなたはそれを世界中で使ってみようとしていますか?

+0

これは、プラットフォームとJVMに依存しているため、Thread.yield()を使用しないでください。あれは正しいですか? wait()を使うほうがYield()の方が良い。私は正しい? – user414967

+0

問題は、制御と同じくらい移植性ではありません。あなたは、スレッド間の任意の形式の同期を行うためにyieldを使って十分な制御を持っていません。利回りが問題を解決するとは思えません。あなたの質問の問題は、あなたが収量について尋ねたことですが、本当になぜ収量が必要だと思ったのかは言いませんでした。 wait/notify/notifyAllを使用して完全に制御するために同期させますが、通常はもっと簡単な方法もあります。あなたは何をしようとしているのですか? – chubbsondubs

0

Thread.yield:これは本質的に現在のスレッドが「CPUをあきらめている」としばらくしていることをシステムに通知するために使用される静的メソッドです。

スレッドスケジューラは、現在のスレッドの代わりに実行する別のスレッドを選択できます。

しかしながら、スレッドスケジューラによってどのように降伏が実装されるかの詳細は、プラットフォームによって異なります。一般的に、特定の方法で動作することに頼るべきではありません。

1.when, after yielding, the thread will get an opportunity to run again; 
2.whether or not the thread forgoes its remaining quantum. 

スレッド優先順位:含ま異なるもの

を任意の時点では、最も優先度の高いスレッドが実行されています。ただし、これは保証されません。スレッドスケジューラは、より低い優先度のスレッドを実行して飢餓を回避することを選択することができる。このため、優先度は、効率化の目的でスケジューリングポリシーに影響を与えるためにのみ使用してください。

0

スレッド優先順位のようなThread.yield()は、OSに対する単なる提案です。 yield()が現在のスレッドを停止するという保証はありません。 OSがスレッドをどこでも停止させる可能性があるため、優先順位の高いスレッドがその時点で実行されることを保証するものではありません。より高い優先度のスレッドがより高い優先度を持つという保証はなく、そうであれば何らかの相違を生じさせます。

IMHO独自のスケジューラーをJavaで作成することはお勧めできません。思うように助けたり、行動したりすることはほとんどありません。

関連する問題