These three functions are often obfuscated.
From the operating system perspective, the OS maintains a ready queue (ready thread queue ). In addition, at a certain time, the cpu only serves the thread in the queue header of the ready queue.
However, the thread being served may feel that the cpu service quality is not good enough, so it exits early, which is yield.
Or the thread that is currently being served needs to sleep for a while, and will continue to be served after waking up. This is sleep.
The sleep method is not recommended and can be used with wait.
It is best to implement this by yourself when the thread exits. It always checks a state in the running state. If this state is true, it will continue to run. If the outside world changes this state variable, the thread will stop running.
Sleep () causes the current thread to enter the stuck state, so the thread executing sleep () will certainly not be executed within the specified time; yield () only enables the current thread to return to the executable state, therefore, the thread that executes yield () may be executed immediately after it enters the executable state.
Sleep () can lead to execution of low-priority threads. Of course, it can also lead to execution of threads with the same priority and higher priority; yield () only threads with the same priority can have execution opportunities.
When wait () is called, the thread will release the lock mark it occupies, so that other synchronized data in the thread's object can be used by other threads.
Waite () and Y () are called in the synchronized function or synchronized block because they operate on the object's "lock flag. If the call is performed in the non-synchronized function or the non-synchronized block, the IllegalMonitorStateException exception may occur at runtime although the compilation is successful.
Thoroughly understand the multi-thread communication mechanism:
Inter-thread Communication
1. Several States of the thread
A thread has four States. Any thread must be in one of these four states:
1) generate (New): The thread object has been generated but has not been started, so it cannot be executed. For example, if a new thread object is generated without calling the start () function on it.
2) Runnable: each system that supports multiple threads has a scheduler, which selects a thread from the thread pool and starts it. When a thread is in the executable state, it may be in the thread pool waiting for the scheduler to start it; or it may be being executed. For example, after the start () method of a thread object is executed, the thread is in the executable state, but it is obvious that the thread is not necessarily being executed at this time.
3) Dead: When a thread ends normally, it is in the Dead state. For example, after a thread's run () function is executed, the thread enters the dead state.
4) Blocked: When a thread is stuck, the system scheduler ignores it and does not schedule it. When a thread in the stuck state returns to the executable state, it may be re-executed. For example, after a thread calls the wait () function, the thread becomes stuck. It can return to the executable state twice only after the thread calls y or yyall twice.
2. Common Function functions under class Thread
2.1 suspend (), resume ()
1) The suspend () function can cause the thread to enter the stuck state. After the thread enters the stuck State through suspend (), the thread will not change back to the executable State unless the resume () message is received.
2) When the suspend () function is called, the thread will not release its "lock flag ".
Example 11:
Class TestThreadMethod extends Thread {
Public static int shareVar = 0;
Public TestThreadMethod (String name ){
Super (name );
}
Public synchronized void run (){
If (shareVar = 0 ){
For (int I = 0; I <5; I ++ ){
ShareVar ++;
If (shareVar = 5 ){
This. suspend (); // (1)
}
}
}
Else {
System. out. print (Thread. currentThread (). getName ());
System. out. println ("shareVar =" + shareVar );
This. resume (); // (2)
}
}
}
Public class TestThread {
Public static void main (String [] args ){
TestThreadMethod t1 = new TestThreadMethod ("t1 ");
TestThreadMethod t2 = new TestThreadMethod ("t2 ");
T1.start (); // (5)
// T1.start (); // (3)
T2.start (); // (4)
}
}
The running result is:
T2 shareVar = 5
I. When the thread generated by code t1 (5) runs at code (1), the thread enters the stuck state. Then the scheduler calls the thread produced by t2 of code (4) from the thread pool. At this time, the shareVar value is not 0, so the statement in else is executed.
Ii. Maybe you will ask, why does t1 not enter the executable status after Code Execution (2? As mentioned above, t1 and t2 are two threads of different objects, while code (1) and (2) only operate on the current object, so the result of thread Execution Code (1) produced by t1 is that the current thread of the object t1 enters the stuck state, and the thread Execution Code generated by t2 (2) the result is to call all the threads in the stopped state of the object t2 back to the executable state.
Iii. Now I have commented out code (4) and removed the comments of code (3). Can t1 be re-executed? The running result is nothing. Why? You may think that when the thread produced by code (5) is executed to code (1), it enters the stuck state; while code (3) the generated thread and the thread produced by code (5) belong to the same object, so when the thread produced by code (3) is executed to code (2, the execution of the thread generated by code (5) can be returned to the executable state. Note that the suspend () function only stops the current thread, but does not release the lock mark obtained by the current thread ". Therefore, when the threads produced by code (5) enter the stuck state, the threads produced by code (3) still cannot be started, because the lock mark of the current object is still occupied by the thread generated by code (5.
2.2 sleep ()
1) The sleep () function has a parameter that enables the thread to enter the stuck state within the specified time. After the specified time, the thread automatically enters the executable state.
2) When the sleep () function is called, the thread will not release its "lock mark ".
Example 12:
Class TestThreadMethod extends Thread {
Class TestThreadMethod extends Thread {
Public static int shareVar = 0;
Public TestThreadMethod (String name ){
Super (name );
}
Public synchronized void run (){
For (int I = 0; I <3; I ++ ){
System. out. print (Thread. currentThread (). getName ());
System. out. println (":" + I );
Try {
Thread. sleep (100); // (4)
}
Catch (InterruptedException e ){
System. out. println ("Interrupted ");
}
}
}
}
Public class TestThread {
Public static void main (String [] args ){
TestThreadMethod t1 = new TestThreadMethod ("t1 ");
TestThreadMethod t2 = new TestThreadMethod ("t2 ");
T1.start (); (1)
T1.start (); (2)
// T2.start (); (3)
}
}
The running result is:
T1: 0
T1: 1
T1: 2
T1: 0
T1: 1
T1: 2
The results show that although sleep () is executed in run (), it does not release the object's "lock flag", unless the code (1) the thread executes the run () function and releases the "Lock mark" of the object. Otherwise, the thread of code (2) will never be executed.
If you comment out code (2) and remove the code (3), the result will be changed:
T1: 0
T2: 0
T1: 1
T2: 1
T1: 2
T2: 2
Because t1 and t2 are the threads of two objects, when thread t1 is stuck through sleep (), the scheduler will call other executable threads from the thread pool, thus thread t2 is started.
Example 13:
Class TestThreadMethod extends Thread {
Public static int shareVar = 0;
Public TestThreadMethod (String name ){
Super (name );
}
Public synchronized void run (){
For (int I = 0; I <5; I ++ ){
System. out. print (Thread. currentThread (). getName ());
System. out. println (":" + I );
Try {
If (Thread. currentThread (). getName (). equals ("t1 "))
Thread. sleep (200 );
Else
Thread. sleep (100 );
}
Catch (InterruptedException e ){
System. out. println ("Interrupted ");
}
}
}
}
Public class TestThread {
Public static void main (String [] args ){
TestThreadMethod t1 = new TestThreadMethod ("t1 ");
TestThreadMethod t2 = new TestThreadMethod ("t2 ");
T1.start ();
// T1.start ();
T2.start ();
}
}
The running result is:
T1: 0
T2: 0
T2: 1
T1: 1
T2: 2
T2: 3
T1: 2
T2: 4
T1: 3
T1: 4
Thread t1 calls sleep (200) and thread t2 calls sleep (100), so the time when thread t2 is in the stuck state is half of thread t1, from the result, the thread T2. T2.
2.3 yield ()
1) The yield () function enables the thread to enter the executable state, and the scheduler re-runs the scheduler from the thread in the executable state. Therefore, the function that calls yield () may be executed immediately.
2) When the yield () function is called, the thread will not release its "lock mark ".
Example 14:
Class TestThreadMethod extends Thread {
Public static int shareVar = 0;
Public TestThreadMethod (String name ){
Super (name );
}
Public synchronized void run (){
For (int I = 0; I <4; I ++ ){
System. out. print (Thread. currentThread (). getName ());
System. out. println (":" + I );
Thread. yield ();
}
}
}
Public class TestThread {
Public static void main (String [] args ){
TestThreadMethod t1 = new TestThreadMethod ("t1 ");
TestThreadMethod t2 = new TestThreadMethod ("t2 ");
T1.start ();
T1.start (); // (1)
// T2.start (); (2)
}
}
The running result is:
T1: 0
T1: 1
T1: 2
T1: 3
T1: 0
T1: 1
T1: 2
T1: 3
The results show that the "Lock flag" of the object is not released when yield () is called ".
If you comment out code (1) and remove the comments of code (2), the result is:
T1: 0
T1: 1
T2: 0
T1: 2
T2: 1
T1: 3
T2: 2
T2: 3
According to the results, although the t1 thread calls yield (), it is immediately executed again.
2.4 differences between sleep () and yield ()
1) sleep () causes the current thread to enter the stuck state, so the thread executing sleep () will certainly not be executed within the specified time; yield () it only enables the current thread to return to the executable State. Therefore, the thread that executes yield () may be executed immediately after it enters the executable state.
2) sleep () can lead to execution of low-priority threads. Of course, it can also lead to execution of threads with the same priority and higher priority; yield () only threads with the same priority can have execution opportunities.
Example 15:
Class TestThreadMethod extends Thread {
Public static int shareVar = 0;
Public TestThreadMethod (String name ){
Super (name );
}
Public void run (){
For (int I = 0; I <4; I ++ ){
System. out. print (Thread. currentThread (). getName ());
System. out. println (":" + I );
// Thread. yield (); (1)
/* (2 )*/
Try {
Thread. sleep (3000 );
}
Catch (InterruptedException e ){
System. out. println ("Interrupted ");
}
}
}
}
Public class TestThread {
Public static void main (String [] args ){
TestThreadMethod t1 = new TestThreadMethod ("t1 ");
TestThreadMethod t2 = new TestThreadMethod ("t2 ");
T1.setPriority (Thread. MAX_PRIORITY );
T2.setPriority (Thread. MIN_PRIORITY );
T1.start ();
T2.start ();
}
}
The running result is:
T1: 0
T1: 1
T2: 0
T1: 2
T2: 1
T1: 3
T2: 2
T2: 3
As can be seen from the results, sleep () can be used to give lower-priority threads the opportunity to execute. Comment out code (2) and remove the comments of code (1). The result is:
T1: 0
T1: 1
T1: 2
T1: 3
T2: 0
T2: 1
T2: 2
T2: 3
It can be seen that when yield () is called, threads with different priorities will never get execution opportunities.
2.5 join ()
After the thread that calls join () is executed, other threads can be executed. In a certain sense, it can implement the synchronization function.
Example 16:
Class TestThreadMethod extends Thread {
Public static int shareVar = 0;
Public TestThreadMethod (String name ){
Super (name );
}
Public void run (){
For (int I = 0; I <4; I ++ ){
System. out. println ("" + I );
Try {
Thread. sleep (3000 );
}
Catch (InterruptedException e ){
System. out. println ("Interrupted ");
}
}
}
}
Public class TestThread {
Public static void main (String [] args ){
TestThreadMethod t1 = new TestThreadMethod ("t1 ");
T1.start ();
Try {
T1.join ();
}
Catch (InterruptedException e ){}
T1.start ();
}
}
The running result is:
0
1
2
3
0
1
2
3
3. common thread functions in class Object
The wait (), Policy (), and policyall () functions are provided by the java. lang. Object class to coordinate multiple threads to access Shared data.
3.1 wait (), notify (), and policyall ()
1) The wait () function has two forms: the first form accepts a millisecond value, used to suspend the thread within a specified period of time, so that the thread enters the stuck state. The second form is without parameters, which means that waite () will continue to stagnate before notify () or notifyAll.
2) When running notify () on an object, it will remove any thread from the thread wait pool and put it in the lock sign waiting pool; when running yyall () on an object () all threads of the object will be removed from the thread wait pool, and they will be placed in the lock sign wait pool.
3) When wait () is called, the thread will release the lock mark it occupies, so that other synchronized data in the thread's object can be used by other threads.
Example 17:
Next, we will modify the example in example 11.
Class TestThreadMethod extends Thread {
Public static int shareVar = 0;
Public TestThreadMethod (String name ){
Super (name );
}
Public synchronized void run (){
If (shareVar = 0 ){
For (int I = 0; I <10; I ++ ){
ShareVar ++;
If (shareVar = 5 ){
Try {
This. wait (); // (4)
}
Catch (InterruptedException e ){}
}
}
}
If (shareVar! = 0 ){
System. out. print (Thread. currentThread (). getName ());
System. out. println ("shareVar =" + shareVar );
This. Y (); // (5)
}
}
}
Public class TestThread {
Public static void main (String [] args ){
TestThreadMethod t1 = new TestThreadMethod ("t1 ");
TestThreadMethod t2 = new TestThreadMethod ("t2 ");
T1.start (); // (1)
// T1.start (); (2)
T2.start (); // (3)
}
}
The running result is:
T2 shareVar = 5
Because t1 and t2 are two different objects, thread t2 call code (5) cannot evoke thread t1. If the comments of code (2) are removed and the code (3) is commented out, the result is:
T1 shareVar = 5
T1 shareVar = 10
This is because when the thread of code (1) is executed to code (4), it enters the stuck state and releases the lock state of the object. Then, the Code (2) thread executes run (). Because the shareVar value is 5 at this time, execute the print statement and call code (5) to make code (1) the thread enters the executable state, and the thread of code (2) ends. When the code (1) thread re-executes, it then executes the for () loop until shareVar = 10, and then prints the shareVar.
3.2 wait (), notify (), and synchronized
Waite () and Y () are called in the synchronized function or synchronized block because they operate on the object's "lock flag. If the call is performed in the non-synchronized function or the non-synchronized block, the IllegalMonitorStateException exception may occur at runtime although the compilation is successful.
Example 18:
Class TestThreadMethod extends Thread {
Public int shareVar = 0;
Public TestThreadMethod (String name ){
Super (name );
New Notifier (this );
}
Public synchronized void run (){
If (shareVar = 0 ){
For (int I = 0; I <5; I ++ ){
ShareVar ++;
System. out. println ("I =" + shareVar );
Try {
System. out. println ("wait ......");
This. wait ();
}
Catch (InterruptedException e ){}
}
}
}
}
Class Notifier extends Thread {
Private TestThreadMethod ttm;
Notifier (TestThreadMethod t ){
Ttm = t;
Start ();
}
Public void run (){
While (true ){
Try {
Sleep (2000 );
}
Catch (InterruptedException e ){}
/* 1 the method to synchronize is not the current object */
Synchronized (ttm ){
System. out. println ("policy ......");
Ttm. Y ();
}
}
}
}
Public class TestThread {
Public static void main (String [] args ){
TestThreadMethod t1 = new TestThreadMethod ("t1 ");
T1.start ();
}
}
The running result is:
I = 1
Wait ......
Using y ......
I = 2
Wait ......
Using y ......
I = 3
Wait ......
Using y ......
I = 4
Wait ......
Using y ......
I = 5
Wait ......
Using y ......
4. Discussions on wait (), notify (), policyall (), suspend (), resume (), and sleep ()
4.1 differences between the two groups of functions
1) When wait () causes the current thread to enter the stagnant state, it will also release the "Lock mark" occupied by the current thread, so that the synchronized Resources in the thread object can be used by other threads in the object; when the suspend () and sleep () enable the current thread to enter the stuck state, the "Lock mark" occupied by the current thread will not be released ".
2) the previous Group of functions must be called in the synchronized function or synchronized block; otherwise, an error occurs during running; the other group of functions can be called in the non-synchronized function and synchronized block.
4.2 trade-off between the two groups of functions
Java2 does not recommend using the last group of functions. Because the "Lock mark" obtained by the current thread is not released when wait () is called, it is easy to cause a "deadlock ".
This article from the CSDN blog, reproduced please indicate the source: http://blog.csdn.net/lxg2000/archive/2007/06/12/1648722.aspx