- ベストアンサー
スレッドの優先順位に関して
ただ今、黒本(徹底攻略 Java2 プログラマ問題集 Platform5.0 対応) を使用しSJC-Pの勉強をしているんですが、スレッドの20番目の問題が どうしてもわからないので質問させて下さい。 下記の問題なんですが コンパイルし実行した結果として正しい物を選ぶという 問題で、答えは「 B A B A B A と表示される」になります。 class MyThread extends Thread{ MyThread(String name){ super(name); } public void run(){ System.out.println(getName()); for(int i=0;i<2;i++){ try{ sleep(1000); }catch(Exception e){} yield(); System.out.println(getName()); }}} class T20{ public static void main(String[] args){ Thread t1 = new MyThread("A"); t1.setPriority(1); t1.start(); Thread t2 = new MyThread("B"); t2.setPriority(10); t2.start(); } } この問題の答えの解説で 優先順位を指定すると必ず高い優先順位のスレッドから 実行が開始するみたいな事が書かれてて、おかしいと思い、 検証してみたところ、私の環境では、結果が何通りも表示されました。 yield()についても私の持っている別の参考書には 「現在実行中のスレッドオブジェクトを実行可能状態に戻し、 他のスレッドに実行できるようにする。ただし優先順位の関係で実行中だったスレッドが再度実行される可能性もある。」 と書かれていて上記の答えに納得が出来ていません。 スレッドの優先順位とyieldに関して お手数ですが、アドバイスよろしくお願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
yieldメソッドは実行可能状態のスレッドに 自身以上の優先順位を持つスレッドがある場合、 そのスレッドに実行権を譲る働きを行います。 実際の動きはともかくとして、 問題として出されてますご質問の例ですと、 yieldメソッドが呼び出されても何も起こりません。 t2がyieldメソッドを呼び出した場合は、 t1はsleepによる実行待ち状態であり、 t1がyieldメソッドを呼び出した場合は、 t2がsleepによる実行待ち状態であるためです。 改めて見て思いますが、これはちょっと問題が悪いですよね。 環境に言及しないのはともかく、断りの1つもないのは 試験の意味合いとしても本末転倒な気がします。
その他の回答 (2)
- ninoue
- ベストアンサー率52% (1288/2437)
このプログラムの場合、シングルコアCPU/シングルスレッド実行のシステムでは"B A B A B A"と決まった順序で実行されるはずです。 しかし最近のプロセッサではマルチCPU、或いはシングルCPUでもH/W的にマルチスレッド実行可能なものが殆どです。 プログラムが最初にスケジュールされる順序は、プログラムのスケジュールリストは全CPU同一のリストを参照しますので優先順序通りになります。 ここで例えば、'A',及び'B'を印字すべきプログラムが同時に別々のCPUで実行中に、途中で外部割込みが優先度の高い'A'プログラム実行中のCPU側に入ることも考えられます。 その場合'A'が中断している間に'B'は続行し、先に'B'が印字されることもありえます。 以上の通り、特にI/Oの割合が多いプログラムでは、細かく見ていくと優先順序通りにはならない場合が多くなります。
補足
連絡が遅くなりすいません。 わかり易い説明をありがとうございます。 シングルコアCPU/シングルスレッド実行のシステムについて おかげ様で理解する事ができましたが、 一つだけyieldに関しては、上のプログラムでいくと、 まず最初に優先順位の高いBがyieldを触れた時点で 実行可能状態に戻りますが、上の私が書いたyieldの説明でいくと 優先順位がBの方が高い為 すぐにまたBが実行状態に戻る事になると思います。 そうするとB A B A B Aにはならないように思うんですが、 もしよろしければyieldについて教えていただけませんか?
- kana_m
- ベストアンサー率40% (26/65)
コード的な答えは「 B A B A B A と表示される」であってると思います。 ただし、t1が実行可能状態になってからの挙動は、 システムでどうスケジュールされているかによって変わるため、 実際に動かしてみても必ずBABABAと表示されるとは限りません。 私もシステムのスケジュールに関しては詳しくありませんが、 スレッドが実行可能になってから実際に実行されるまでに 少し受け待ち時間みたいなものがあるのだと思います。 その間にt2が実行可能になれば、優先度の高いt2から実行されますし 同様にt1がsleepから復帰して実行可能になった時にも t1が実行されるまでにt2が実行可能になればt2から実行されるのではないでしょうか。 間違っていたらすいません。
補足
大変わかり易い説明ありがとうございます。 試験に関しては、優先度が指定してある場合、数値の高いスレッドから 実行が開始されると理解するようにしました。 yieldに関しては、この問題のコード的な答えとして考えると、 実行中のスレッドがyieldを実行すると一度実行可能状態に戻り、 優先度関係なく、必ず他のスレッドに実行を譲ると考えてもよろしいですか?
お礼
返事が遅くなり申し訳ございません。 具体的なソースの流れ、yieldメソッドの意味合い を教えていただきありがとうございます。 yieldを呼び出した時は常にスレッドは寝ている状態なんですね。 スレッドの問題は優先順位など、答えがすごい選びにくいものも 多いですのでその場の状況に応じて適切な対応をしたいと思います。 本当にありがとうございました。