スレッドの譲歩: yield()
yield() の関数は譲歩です。これにより、現在のスレッドが「実行状態」から「準備完了状態」に移行できるようになり、同じ優先順位を持つ他の待機スレッドが実行権を取得できるようになります。ただし、現在のスレッドが yield() を呼び出した後、他のスレッドが実行権を取得できるという保証はありません。待機中のスレッドは同じ優先順位を持ちますが、現在のスレッドが「実行状態」になって実行を継続する可能性もあります。
例:
class ThreadA extends Thread{ public ThreadA(String name){ super(name); } public synchronized void run(){ for(int i=0; i <10; i++){ System.out.printf("%s [%d]:%d\n", this.getName(), this.getPriority(), i); // i整除4时,调用yield if (i%4 == 0) Thread.yield(); } } } public class YieldTest{ public static void main(String[] args){ ThreadA t1 = new ThreadA("t1"); ThreadA t2 = new ThreadA("t2"); t1.start(); t2.start(); } }
(ある時刻) 実行結果:
t1 [5]:0 t2 [5]:0 t1 [5]:1 t1 [5]:2 t1 [5]:3 t1 [5]:4 t1 [5]:5 t1 [5]:6 t1 [5]:7 t1 [5]:8 t1 [5]:9 t2 [5]:1 t2 [5]:2 t2 [5]:3 t2 [5]:4 t2 [5]:5 t2 [5]:6 t2 [5]:7 t2 [5]:8 t2 [5]:9
結果の説明:
「スレッド t1」が整数 4 の場合に「スレッド t2」に切り替わりませんでした。これは、yield() によってスレッドが「実行状態」から「準備完了状態」に入ることができるが、必ずしも他のスレッドが CPU 実行権を取得できるわけではない (つまり、他のスレッドが「実行状態」に入る) ことを示しています。 ")、この「他のスレッド」が現在 yield() を呼び出しているスレッドと同じ優先度を持っている場合でも。
yield() と wait() の比較:
wait() の機能は、現在のスレッドを「実行状態」から「待機 (ブロック) 状態」に移行させ、同期ロックを解放することであることがわかります。 yield() の機能は降参することであり、現在のスレッドを「実行状態」から離れることにもなります。それらの違いは次のとおりです:
(1) wait() はスレッドが「実行状態」から「待機 (ブロック) 状態」に入ることができるのに対し、yield() はスレッドが「実行状態」から「準備完了状態」に入ることができます。実行状態」。
(2) wait() により、スレッドは保持しているオブジェクトの同期ロックを解放しますが、yield() メソッドはロックを解放しません。
次の例は、yield() がロックを解放しないことを示しています:
public class YieldLockTest{ private static Object obj = new Object(); public static void main(String[] args){ ThreadA t1 = new ThreadA("t1"); ThreadA t2 = new ThreadA("t2"); t1.start(); t2.start(); } static class ThreadA extends Thread{ public ThreadA(String name){ super(name); } public void run(){ // 获取obj对象的同步锁 synchronized (obj) { for(int i=0; i <10; i++){ System.out.printf("%s [%d]:%d\n", this.getName(), this.getPriority(), i); // i整除4时,调用yield if (i%4 == 0) Thread.yield(); } } } } }
(特定の時間) 実行結果:
t1 [5]:0 t1 [5]:1 t1 [5]:2 t1 [5]:3 t1 [5]:4 t1 [5]:5 t1 [5]:6 t1 [5]:7 t1 [5]:8 t1 [5]:9 t2 [5]:0 t2 [5]:1 t2 [5]:2 t2 [5]:3 t2 [5]:4 t2 [5]:5 t2 [5]:6 t2 [5]:7 t2 [5]:8 t2 [5]:9
結果の説明:
2 つのスレッド t1 と t2 がメインスレッド main で開始されます。 t1 と t2 は、run() 内の同じオブジェクト、つまり synchronized(obj) の同期ロックを参照します。ただし、t1 の実行中に Thread.yield(); が呼び出されますが、t2 は CPU の実行権を取得しません。なぜなら、t1 は「obj が保持している同期ロック」を解放していないからです。
スレッド sleep: sleep()
sleep() は Thread.java で定義されています。
sleep() は、現在のスレッドをスリープさせるために使用されます。つまり、現在のスレッドは「実行状態」から「スリープ (ブロック) 状態」に入ります。 sleep() はスリープ時間を指定し、スレッドのスリープ時間はスリープ時間以上になります。スレッドが再び目覚めると、スレッドは「ブロック状態」から「準備完了状態」に変わり、 CPUのスケジューリング実行。
例:
class ThreadA extends Thread{ public ThreadA(String name){ super(name); } public synchronized void run() { try { for(int i=0; i <10; i++){ System.out.printf("%s: %d\n", this.getName(), i); // i能被4整除时,休眠100毫秒 if (i%4 == 0) Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } } public class SleepTest{ public static void main(String[] args){ ThreadA t1 = new ThreadA("t1"); t1.start(); } }
実行結果:
t1: 0 t1: 1 t1: 2 t1: 3 t1: 4 t1: 5 t1: 6 t1: 7 t1: 8 t1: 9
結果の説明:
プログラムは比較的単純で、メインスレッド main でスレッド t1 を開始します。 t1 の開始後、t1 の計算 i が 4 で割り切れる場合、t1 は Thread.sleep(100) を通じて 100 ミリ秒間スリープします。
sleep() と wait() の比較:
wait() の機能は、現在のスレッドを「実行状態」から「待機 (ブロック) 状態」に移行させ、同期ロックを解放することであることがわかります。 sleep() の機能は、現在のスレッドを「実行状態」から「スリープ (ブロック) 状態」に移行させることでもあります。
ただし、wait() はオブジェクトの同期ロックを解放しますが、sleep() はロックを解放しません。
次の例は、sleep() がロックを解放しないことを示しています。
public class SleepLockTest{ private static Object obj = new Object(); public static void main(String[] args){ ThreadA t1 = new ThreadA("t1"); ThreadA t2 = new ThreadA("t2"); t1.start(); t2.start(); } static class ThreadA extends Thread{ public ThreadA(String name){ super(name); } public void run(){ // 获取obj对象的同步锁 synchronized (obj) { try { for(int i=0; i <10; i++){ System.out.printf("%s: %d\n", this.getName(), i); // i能被4整除时,休眠100毫秒 if (i%4 == 0) Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } } } }
実行結果:
t1: 0 t1: 1 t1: 2 t1: 3 t1: 4 t1: 5 t1: 6 t1: 7 t1: 8 t1: 9 t2: 0 t2: 1 t2: 2 t2: 3 t2: 4 t2: 5 t2: 6 t2: 7 t2: 8 t2: 9
結果の説明:
メインスレッド main で 2 つのスレッド t1 と t2 が開始されます。 t1 と t2 は、run() 内の同じオブジェクト、つまり synchronized(obj) の同期ロックを参照します。ただし、t1 の実行中に Thread.sleep(100) が呼び出されますが、t2 は CPU 実行権を取得しません。なぜなら、t1 は「obj が保持している同期ロック」を解放していないからです。
synchronized (obj) をコメントアウトしてプログラムを再度実行すると、t1 と t2 が相互に切り替わることに注意してください。以下は、synchronized(obj) にアノテーションを付けた後のソース コードです。
public class SleepLockTest{ private static Object obj = new Object(); public static void main(String[] args){ ThreadA t1 = new ThreadA("t1"); ThreadA t2 = new ThreadA("t2"); t1.start(); t2.start(); } static class ThreadA extends Thread{ public ThreadA(String name){ super(name); } public void run(){ // 获取obj对象的同步锁 // synchronized (obj) { try { for(int i=0; i <10; i++){ System.out.printf("%s: %d\n", this.getName(), i); // i能被4整除时,休眠100毫秒 if (i%4 == 0) Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } // } } } }
Java の thread yield() メソッドと thread sleep sleep() メソッドの詳細な説明については、PHP 中国語 Web サイトの関連記事に注目してください。