Thread concessions: yield()
The purpose of yield() is to give in. It can allow the current thread to enter the "ready state" from the "running state", so that other waiting threads with the same priority can obtain execution rights; however, it cannot guarantee that after the current thread calls yield(), other threads with the same priority will definitely obtain execution rights; it may also be that the current thread enters the "running state" and continues to run!
Example:
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); // When i is divided by 4, call 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(); } } (One time) operation result:
t1 [5]:0t2 [5]:0t1 [5]:1t1 [5]:2t1 [5]:3t1 [5]:4t1 [5]:5t1 [5]:6t1 [5]:7t1 [5]:8t1 [5]:9t2 [5]:1t2 [5]:2t2 [5]:3t2 [5]:4t2 [5]:5t2 [5]:6t2 [5]:7t2 [5]:8t2 [5]:9
Results description:
When "thread t1" can be integered by 4, it does not switch to "thread t2". This shows that although yield() can allow threads to enter the "ready state" from "running state", it does not necessarily allow other threads to obtain CPU execution rights (i.e., other threads enter the "running state"), even if this "other thread" has the same priority as the thread currently calling yield().
Comparison of yield() and wait():
We know that the function of wait() is to allow the current thread to enter the "wait (blocking) state from the "running state" and also release the synchronization lock. The function of yield() is to give in, which will also cause the current thread to leave the "running state". Their differences are:
(1) wait() is to let the thread enter the "wait (blocking) state" from the "running state", while not yield() is to let the thread enter the "ready state" from the "running state".
(2) wait() is a synchronization lock that will thread release the object it holds, while the yield() method will not release the lock.
The following example shows that yield() will not release the lock:
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(){ // Get synchronized (obj) { for(int i=0; i <10; i++){ System.out.printf("%s [%d]:%d/n", this.getName(), this.getPriority(), i); // When i is divided by 4, call yield if (i%4 == 0) Thread.yield(); } } } } } } (One time) result:
t1 [5]:0t1 [5]:1t1 [5]:2t1 [5]:3t1 [5]:4t1 [5]:5t1 [5]:6t1 [5]:7t1 [5]:8t1 [5]:9t2 [5]:0t2 [5]:1t2 [5]:2t2 [5]:3t2 [5]:4t2 [5]:5t2 [5]:6t2 [5]:7t2 [5]:8t2 [5]:9
Results description:
Two threads t1 and t2 are started in the main thread main. t1 and t2 will refer to the synchronization lock of the same object in run(), that is, synchronized(obj). During the t1 operation, although it will call Thread.yield(); t2 will not obtain CPU execution rights. Because t1 does not release the "synchronous lock held by obj"!
Thread sleep: sleep()
sleep() is defined in Thread.java.
The function of sleep() is to let the current thread sleep, that is, the current thread will enter from the "running state" to the "sleep (blocking) state". sleep() will specify the sleep time, and the thread sleep time will be greater than/equal to the sleep time; when the thread is awakened again, it will change from a "blocking state" to a "ready state", waiting for the CPU to be scheduled to execute.
Example:
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); // When i can be divided by 4, sleep for 100ms 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(); } } Running results:
t1: 0t1: 1t1: 2t1: 3t1: 4t1: 5t1: 6t1: 7t1: 8t1: 9
Results description:
The program is relatively simple, start thread t1 in the main thread main. After t1 is started, when the calculation i in t1 can be divisible by 4, t1 will sleep for 100 milliseconds through Thread.sleep(100).
Comparison of sleep() and wait():
We know that the function of wait() is to allow the current thread to enter the "wait (blocking) state from the "running state" and also release the synchronization lock. The function of sleep() is to let the current thread enter the "sleep (blocking) state" from the "running state".
However, wait() releases the object's synchronization lock, while sleep() does not release the lock.
The following example shows that sleep() will not release the lock.
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(){ // Get the synchronization lock of the obj object synchronized (obj) { try { for(int i=0; i <10; i++){ System.out.printf("%s: %d/n", this.getName(), i); // When i can be divided by 4, sleep for 100ms if (i%4 == 0) Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } } } } } } } } Running results:
t1: 0t1: 1t1: 2t1: 3t1: 4t1: 5t1: 6t1: 7t1: 8t1: 9t2: 0t2: 1t2: 2t2: 3t2: 4t2: 5t2: 6t2: 7t2: 8t2: 9
Results description:
Two threads t1 and t2 are started in the main thread main. t1 and t2 will refer to the synchronization lock of the same object in run(), that is, synchronized(obj). During t1 running, although it will call Thread.sleep(100); t2 will not obtain CPU execution rights. Because t1 does not release the "synchronous lock held by obj"!
Note that if we comment out synchronized (obj) and execute the program again, t1 and t2 can be switched to each other. The following is the source code after the comment tune 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(){ // Get the synchronization lock of the obj object// synchronized (obj) { try { for(int i=0; i <10; i++){ System.out.printf("%s: %d/n", this.getName(), i); // When i can be divided by 4, sleep for 100ms if (i%4 == 0) Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); }// } } } }