1. ホーム
  2. java

[解決済み] yield()の主な用途と、join()やinterrupt()との違いは何ですか?

2022-10-26 16:16:58

質問

の使い方で少し迷っています。 Thread.yield() メソッドの使用について少し混乱しています。yield()は「スレッドの実行を阻止するために使用される」とも書いてありました。

私の質問は

  1. を使用した場合、以下のコードは同じ出力になると思います。 yield() を使用した場合と使用しなかった場合の両方で、同じ出力になると思います。これは正しいのでしょうか?

  2. の主な用途は、実際には何ですか? yield() ?

  3. どのような点で yield() とは異なり join()interrupt() のメソッドを使用しますか?

コード例です。

public class MyRunnable implements Runnable {

   public static void main(String[] args) {
      Thread t = new Thread(new MyRunnable());
      t.start();

      for(int i=0; i<5; i++) {
          System.out.println("Inside main");
      }
   }

   public void run() {
      for(int i=0; i<5; i++) {
          System.out.println("Inside run");
          Thread.yield();
      }
   }
}

を使っても使わなくても同じ出力が得られます。 yield() :

Inside main
Inside main
Inside main
Inside main
Inside main
Inside run
Inside run
Inside run
Inside run
Inside run

どのように解決するのですか?

ソース http://www.javamex.com/tutorials/threads/yield.shtml

Windows

Hotspotの実装では、その方法として Thread.yield() が動作する方法が がJava 5とJava 6の間で変更されました。

Java5では Thread.yield() はWindows APIコールを呼び出します。 Sleep(0) . これは の特別な効果があります。 現在のスレッドの量子をクリアする と に置くという のキューの最後に置きます。 優先度 . 言い換えれば つまり、同じ優先度のすべての実行可能なスレッド(およびより高い優先度のスレッド)は、降伏したスレッドが次に実行される前に実行する機会を得ます。 は、降伏したスレッドが次にCPU時間を与えられる前に実行する機会を得ます。 CPU時間が与えられる前に実行する機会を得ます。最終的に再スケジューリングされるとき、そのスレッドは で戻ってきます。 完全量子 しかし、降伏したときから残っている量子を持ち越すことはできません。 を持ち越さない。この動作は この動作は、スリープしているスレッドが1つの量子値(実質的に10の1/3)を失うゼロ以外のスリープとは少し異なります。 この動作は、スリーピングスレッドが一般的に1量子値(実質、10または15ms刻みの1/3)を失う非ゼロスリープとは少し異なります。

Java 6 では、この動作が変更されました。Hotspot VM は現在 Thread.yield() を実装し、Windows の SwitchToThread() APIコールを使用します。この呼び出しは は現在のスレッドを をあきらめさせます。 現在のタイムスライス しかし、その であり、量子全体ではありません。これは、他のスレッドの優先順位によって、降伏するスレッドが スレッドの優先順位によっては、降参したスレッドが でスケジュールされます。 周期後に . (の項を参照)。 スレッドスケジューリング を参照してください。 のセクションを参照してください)。

リナックス

Linuxでは、Hotspotは単に sched_yield() . この呼び出しの結果は この呼び出しの結果は、Windowsの場合とは少し異なり、より厳しいものになる可能性があります。 Windows の場合よりも深刻です。

  • 降伏したスレッドは、CPU の別のスライスを取得できません。 まで すべて 他のスレッドがCPUのスライスを持つまで ;
  • (少なくともカーネル 2.6.8 以降) では、スレッドが降参したという事実は、 スケジューラのヒューリスティックによって暗黙のうちに考慮されます。 によって暗黙のうちに考慮されるようになりました。 したがって、暗黙のうちに、降伏したスレッドには、将来スケジュールされるときに、より多くの CPU が与えられる可能性があります。

(のセクションを参照してください)。 スレッドスケジューリング のセクションを参照してください。 のセクションを参照してください)。

いつ使うか yield() ?

私なら ほとんどない . その動作は標準的に定義されているわけではありません。 また、yield()で行いたいタスクを実行するには、一般的にもっと良い方法があります。 一般的には、yield()で実行したいタスクを実行するためのより良い方法があります。

  • もしあなたが CPU の一部だけを使用する を使用する場合、スレッドが最後の処理で使用した CPU の量を推定することで、より制御しやすい方法でこれを行うことができます。 スレッドが最後の処理の塊でどれだけの CPU を使ったかを推定し、次に スリーピング とします。 を行う。 sleep() メソッドを参照してください。
  • であれば プロセスやリソースを待っている が完了したり利用可能になったりするのを待つのであれば、より効率的な方法があります。 例えば join() を使って他のスレッドが完了するのを待つ、などです。 は wait/notify メカニズムを使用して、あるスレッドが他のスレッドにタスク完了のシグナルを送ることができるようにします。 または、理想的には、Java 5の並行処理構造の1つである のような並行処理コンストラクトを使うのが理想的です。 セマフォ または ブロッキングキュー .