This article follows the previous article "Detailed Explanation of Java Multithreading Examples (I)".
4. The blocking state and thread control of Java multithreads
Several specific types of Java blocking have been mentioned above. Let’s take a look at the main methods that cause Java thread blockage.
1.join()
join - Let one thread wait for another thread to complete before continuing execution. If thread A is called in thread B's join() method in thread execution body, thread A is blocked and only after thread B is known to have completed thread B's execution, A can continue to execute.
public class ThreadTest { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 30) { thread.start(); try { thread.join(); // main thread needs to wait for the thread thread to execute before continuing to execute} catch (InterruptedException e) { e.printStackTrace(); } } } } } } } } } } } } } } } } } } } } } } } }2.sleep()
sleep -- Let the currently executing thread pause the specified time and enter a blocking state. During the period of time it sleeps, the thread will not get an opportunity to execute because it is not in the ready state. Even if there are no other executable threads in the system at this time, the threads in sleep() will not execute. Therefore, the sleep() method is often used to pause thread execution.
As mentioned earlier, when the start() method of the newly created thread is called, the thread enters the ready state and may obtain the CPU time slice at some time to execute. If you want the new thread to execute immediately with certain necessity, just call sleep(1) of the original thread directly.
public class ThreadTest { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 30) { thread.start(); try { Thread.sleep(1); // Make thread sure to be executed immediately} catch (InterruptedException e) { e.printStackTrace(); } } } } } } } } } } } } } } } } } } } } } } } }Note: Sleeping for one millisecond is enough, because the CPU will not be idle and will switch to the newly created thread.
3. Background thread (Daemon Thread)
Concept/Purpose: Background threads mainly provide services to other threads (relatively called foreground threads), or "daemon threads". Such as the garbage collection thread in the JVM.
Life cycle: The life cycle of a background thread is related to the life cycle of the foreground thread. It is mainly reflected in: when all foreground threads enter the dead state, the background thread will automatically die (in fact, this is easy to understand, because the purpose of the background thread is to serve the foreground thread. Since all foreground threads have died, what's the use of it still keeping it... Great! !).
Setting background thread: Calling the setDaemon(true) method of the Thread object can set the specified thread as a background thread.
public class ThreadTest { public static void main(String[] args) { Thread myThread = new MyThread(); for (int i = 0; i < 100; i++) { System.out.println("main thread i = " + i); if (i == 20) { myThread.setDaemon(true); myThread.start(); } } } }}class MyThread extends Thread { public void run() { for (int i = 0; i < 100; i++) { System.out.println("i = " + i); try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}Determine whether the thread is a background thread: call the isDeamon() method of the thread object.
Note: The main thread is the foreground thread by default, the child thread created in the foreground thread creation is the foreground thread by default, and the thread created in the background thread is the background thread by default. When calling the setDeamon(true) method to set the foreground thread as a background thread, it needs to be before the start() method is called. After the threads died the day before yesterday, the JVM notifies the background thread to die, but it takes a certain amount of time from receiving the instructions to responding.
4. Change the priority of threads/setPriority():
Each thread has a certain priority when executing, and threads with high priority have more execution opportunities. Each thread has the same priority as the thread that created it. The main thread has normal priority by default.
Set thread priority: setPriority(int priorityLevel). The parameter priorityLevel range is between 1-10, and the commonly used three static constant values are as follows:
MAX_PRIORITY:10
MIN_PRIORITY:1
NORM_PRIORITY:5
Get thread priority: getPriority().
Note: A thread object with higher thread priority only means that this thread has more execution opportunities, rather than priority execution.
public class ThreadTest { public static void main(String[] args) { Thread myThread = new MyThread(); for (int i = 0; i < 100; i++) { System.out.println("main thread i = " + i); if (i == 20) { myThread.setPriority(Thread.MAX_PRIORITY); myThread.start(); } } } }}class MyThread extends Thread { public void run() { for (int i = 0; i < 100; i++) { System.out.println("i = " + i); } }}5. Thread concessions: yield()
The basic role of yield() has been discussed in the previous blog post. At the same time, the yield() method is also related to thread priority. When a thread calls the eiled() method to switch from the running state to the ready state, the CPU will only select threads with the same priority or higher priority as the thread from the ready state thread queue to execute.
public class ThreadTest { public static void main(String[] args) { Thread myThread1 = new MyThread1(); Thread myThread2 = new MyThread2(); myThread1.setPriority(Thread.MAX_PRIORITY); myThread2.setPriority(Thread.MIN_PRIORITY); for (int i = 0; i < 100; i++) { System.out.println("main thread i = " + i); if (i == 20) { myThread1.start(); myThread2.start(); Thread.yield(); } } } }}class MyThread1 extends Thread { public void run() { for (int i = 0; i < 100; i++) { System.out.println("myThread 1 -- i = " + i); } }}class MyThread2 extends Thread { public void run() { for (int i = 0; i < 100; i++) { System.out.println("myThread 2 -- i = " + i); } }}Series of articles:
Explanation of Java multi-threaded instances (I)
Detailed explanation of Java multi-threaded instances (II)
Detailed explanation of Java multi-threaded instances (III)