Threads under certain conditions, the state will change. There are several states for a thread:
1. New state: A new Thread object was created.
2. Ready state (Runnable): After the thread object is created, other threads call the object's start () method. The thread in this state is in the "Running thread pool" and becomes operational, waiting only for the CPU to be used. That is, in the ready state of the process, except the CPU, all the other resources required to run are fully available.
3, running State (Running): The ready state of the thread gets the CPU, executes the program code.
4, blocking State (Blocked): Blocking state is the thread for some reason to abandon the use of the CPU, temporarily stop running. Until the thread is in a ready state, the opportunity to go to the running state is reached.
There are three types of blocking:
(1), waiting for blocking: The running thread executes the wait () method, which frees all resources that are consumed, and the JVM puts the thread into the "waiting pool." After entering this state, it is not automatically awakened and must rely on other threads to invoke the Notify () or Notifyall () method to be awakened.
(2), synchronous blocking: When a running thread acquires a synchronization lock on an object, if the synchronization lock is occupied by another thread, the JVM puts the thread into the lock pool.
(3), other blocking: The running thread executes the sleep () or join () method, or when an I/O request is made, the JVM will place the thread in a blocked state. When the sleep () state times out, join () waits for the thread to terminate or time out, or the I/O process finishes, the thread is re-entered in a ready state.
5. Dead State (Dead): The thread finishes executing or exits the run () method because of an exception, and the thread ends the life cycle.
The state transition diagram for thread changes is as follows:
Note: To get the lock tag for an object, you are given permission to use the object (the critical section). That is, the thread gets the resources it needs to run, enters the ready state, and can run with just the CPU. Because when wait () is called, the thread releases the "lock flag" that it occupies, so that the thread is only able to get the resources to enter the ready state.
Here's a little explanation:
1, the implementation of the thread has two ways, one is to inherit the thread class, the second is to implement the Runnable interface, but anyway, when we new this object, the thread entered the initial state;
2. When the object calls the start () method, it enters the ready state;
3, when it is ready, when the object is selected by the operating system, to obtain the CPU time slice will enter the running state;
4. After entering the operating state, the situation is more complicated.
4.1, the Run () method or the main () method ends, the thread will enter the terminating state;
4.2. When a thread calls its own sleep () method or the Join () method of another thread, the process yields the CPU and then goes into a blocking state (the state stops the current thread, but does not release the occupied resource when the sleep () function is called, and the thread does not release its "lock Flag". )。 When sleep () ends or join () ends, the thread enters the operational state and continues to wait for the OS to allocate CPU time slices. Typically, sleep () is used when waiting for a resource to be ready: After the test discovery condition is not met, let the thread block for a period of time and then re-test until the condition is satisfied.
4.3, the thread calls the yield () method, which means to discard the currently obtained CPU time slice, return to the ready state, when with other processes in the same competition state, the OS may then let this process into the running state; call yield () The effect is equivalent to the scheduler thinking that the thread has executed enough time slices to go to another thread. Yield () simply returns the current thread back to the executable state, so the thread executing yield () is likely to be executed immediately after entering the executable state.
4.4, when the thread has just entered the operational state (note, not yet running), found that the resource to be called is Synchroniza (synchronous), get not the lock tag, will immediately enter the lock pool state, waiting for the lock tag (in this case, the lock pool may already have other threads waiting to get the lock tag, At this point they are in the queue state, on a first-come-first-served basis, once the thread obtains the lock tag, it goes into a ready state, waiting for the OS to allocate CPU time slices;
4.5. Suspend () and resume () methods: Two methods are used, suspend () causes the thread to go into a blocking state, does not automatically recover, and must be called by its corresponding resume () to allow the thread to re-enter the executable state. Typically, suspend () and resume () are used when waiting for the result of another thread: After the test finds that the result has not yet been generated, the thread is blocked and the other thread produces the result, calling resume () to restore it.
4.6, Wait () and Notify () method: When the thread calls the Wait () method, it enters the waiting queue (which frees all the resources that it occupies, unlike the blocking state), which cannot be automatically awakened after entering this state, and must rely on other threads to invoke notify () or the Notifyall () method can be awakened (because notify () only wakes up a thread, but we are not sure which thread is specifically awakened, perhaps the thread we need to wake up cannot be awakened, so in practice it is generally used with the Notifyall () method, Wake up some threads), the thread is awakened and enters the lock pool, waiting for the lock token to be acquired.
Wait () causes the thread to enter a blocking state, which has two forms:
One allows you to specify a period of time in milliseconds as a parameter, and the other without parameters. The former when the corresponding notify () is called or exceeds the specified time, the thread re-enters the executable state is ready state, the latter must be the corresponding notify () is called. When wait () is called, the thread releases the "lock flag" that it occupies, making other synchronized data in the object that the thread resides in can be used by other threads. Waite () and notify () because they operate on the object's lock flags, they must be called in the synchronized function or Synchronizedblock. If the call is made in the non-synchronized function or Non-synchronizedblock, the illegalmonitorstateexception exception will occur at run time, although it can be compiled.
Note the difference: At first glance, the Wait () and notify () methods have nothing to do with the suspend () and the Resume () methods, but in fact they are quite different. The core of the difference is that the suspend () and all other methods described above do not release the locks that are occupied (if they are occupied), while the two methods of Wait () and notify () are the opposite.
The core differences above lead to a series of differences in detail
First, all the methods described earlier are subordinate to the thread class, but the wait () and notify () methods are directly subordinate to the object class, that is, all objects have this pair of methods. At first glance this is very magical, but in fact it is very natural, because this pair of methods when blocking to release the lock occupied, and the lock is any object has, call any object's wait () method causes the thread to block, and the lock on the object is freed. The Notify () method that invokes an arbitrary object causes a randomly selected unblocking in the thread that is blocked by calling the wait () method of the object (but is not really executable until the lock is acquired).
Second, all the methods described earlier can be called anywhere, but the wait () and notify () methods must be called in the Synchronized method or block, and the reason is simple, only in synchronized methods or blocks where the current line friend occupy the lock. Only locks can be released. Similarly, locks on objects that call this pair of methods must be owned by the current thread, so that locks can be freed. Therefore, this pair of method calls must be placed in such a synchronized method or block where the locked object of the method or block is the object that invokes the pair of methods. If this condition is not met, the program can still compile, but the illegalmonitorstateexception exception will occur at run time.
The above characteristics of the wait () and notify () methods determine that they are often used with synchronized methods or blocks. A comparison between them and the operating system's interprocess communication mechanism reveals their similarity: the Synchronized method or block provides functionality similar to the operating system primitives, and their execution is not interfered by the multithreading mechanism, which is equivalent to block and wake up Primitives (this pair of methods are declared as synchronized). Their combination allows us to implement an array of sophisticated inter-process communication algorithms (such as semaphore algorithms) on the operating system, and to solve a variety of complex inter-threading communication problems.
The Wait () and notify () methods are finally explained in two points:
First: Calling the Notify () method causes the unblocked thread to be randomly selected from the thread that was blocked by calling the wait () method of the object, and we cannot predict which thread will be selected, so be careful when programming, and avoid problems with this uncertainty.
Second: In addition to notify (), there is also a method Notifyall () can also play a similar role, the only difference is that the call to the Notifyall () method will be called by the Wait () method of the object is blocked all at once unblocked all the threads. Of course, only the thread that gets the lock can go into the executable state.
The difference between the start and the Run method in a thread;
The difference between the run () and start () methods in the thread class is as follows:
Run () method: Calls the Runnable object's run () method within this thread, and can be repeated multiple calls;
Start () method: Starts a thread, calls the Runnable object's Run () method, and cannot start a thread multiple times;
Start method:
This method starts a thread and creates a thread that really implements multithreading. Instead of waiting for the code in the Run () method to complete, you can then execute the following code. This thread of start () is in a ready state, and the Run () method is executed when the CPU's time slice is obtained. The run () method contains the contents of the thread to be executed, and the run () method ends and the thread terminates.
Run Method:
Starting a thread by using the Run method is actually invoking a method in a class that is called in a normal way. Does not create a thread, there is still only one main thread in the program, you must wait until the code inside the Run () method executes before proceeding with the following code, so that you do not achieve the purpose of writing the thread.
What is the state of the thread, and the difference between the start and the Run method in the thread