1. Scheduling and management of Java threads
The current operating system has provided a very powerful thread management capability. Java does not need to carry out independent thread management and scheduling, but hands over the task of thread scheduling and management to the operating system.
2. Thread scheduling and time slice
1. CPU time slice
Now the computing power of CPU is very fast, and it can run 2 billion calculations per second at 2Ghz. Therefore, the CPU time can be segmented from the millisecond level, and each segment is called a CPU time slice. For different operating systems and CPUs, the length of CPU time slice is also different.
At present, the scheduling of threads in the operating system is based on CPU time slice. Each thread can execute the command only after obtaining the CPU time slice.
The thread that has obtained the CPU time slice is in the running state, and the thread that has not obtained the CPU time slice, but is waiting to obtain the CPU time slice to run is in the ready state.
2. Thread scheduling
At present, there are two main ways of thread scheduling: time-sharing scheduling and preemptive scheduling
1. Time sharing scheduling
The CPU distributes the time slice evenly to each thread, and all CPUs occupy the CPU time slice in turn.
This method is fair to each thread in the scheduling of CPU time slices. It is similar to queuing in life. One by one, it takes up CPU time slices, and then queue at the end of the queue.
2. Preemptive scheduling
The system schedules threads according to their priority. If the priority of threads is the same, a thread is randomly selected to allocate CPU time slice.
Theoretically, threads with high priority get more CPU time slices over a period of time.
Because the thread scheduling models of most operating systems are preemptive, and the thread scheduling of Java is entrusted to the operating system, the thread scheduling mode in Java is also preemptive.
3. Java thread priority
public class TestThreadPriority { public static void main(String[] args) throws InterruptedException { long start = System.currentTimeMillis(); Demo[] demos = new Demo[10]; // Create 10 threads and set the priority of threads to 0-10 respectively for (int i = 0; i < demos.length; i++) { demos[i] = new Demo(); demos[i].setPriority(i + 1); } // Start thread for (int i = 0; i < demos.length; i++) { demos[i].start(); } // Let the asynchronous thread run for 0.1s Thread.sleep(100); // Stop the asynchronous thread. The stop method has been deprecated. This is just a demonstration for (int i = 0; i < demos.length; i++) { demos[i].stop(); } long end = System.currentTimeMillis(); // Here we calculate how much time it really takes for 10 threads from creation to completion System.out.println("main The thread took from starting to closing:" + (end - start) + "millisecond"); // Print the num value in the class to see how much it becomes // From the size of this value, we can roughly know the proportion of running time of each thread for (int i = 0; i < demos.length; i++) { System.out.println("Thread priority is:" + demos[i].getPriority() + ",num For:" + demos[i].num); } } } class Demo extends Thread { public long num = 0; @Override public void run() { for (long i = 0; ; i++) { num++; } } }
The running results of my computer are as follows:
main It took 8262 milliseconds from thread startup to thread shutdown Thread priority: 1, num For: 9122402 Thread priority: 2, num Is: 0 Thread priority: 3, num For: 9154161 Thread priority: 4, num Is: 0 Thread priority: 5, num For: 24016156 Thread priority: 6, num Is: 0 Thread priority: 7, num 2519810813 Thread priority: 8, num 2546229794 Thread priority: 9, num For: 2615067015 Thread priority: 10, num Is: 2603997818
It can also be seen from the results:
- Overall, the higher the priority of a thread, the greater the chance that the thread will get execution. The num size of priority > 6 and < = 6 is not in the same order of magnitude
- The acquisition of execution opportunities is random, and those with high priority may not get more execution times. For example, threads with priorities of 2, 4 and 6 do not get time slices to execute, and threads with lower priorities get time slices instead.
2. Thread life cycle
There are six states in the life cycle of threads in Java.
1. 6 thread states
In the Thread class, the threadStatus attribute is used to save the Thread state, and the getState() method is used to obtain the Thread state.
// Save thread state using int type private volatile int threadStatus; // Get thread status public State getState() { // get current thread state return jdk.internal.misc.VM.toThreadState(threadStatus); }
State class is an internal enumeration class of Thread class, as follows:
public enum State { NEW, // newly build RUNNABLE, // Operation, including the operation and ready status of the operating system BLOCKED, // block WAITING, // wait for TIMED_WAITING, // Time limited waiting TERMINATED; // termination }
1. NEW construction
When the thread is created but the start() method has not been called, it is a new state
Verification Code:
public class TestThreadState { public static void main(String[] args) { Thread thread = new Thread(); System.out.println("Thread status is:" + thread.getState()); } }
The output result is:
Thread status is: NEW
2. RUNNABLE operation
In Java, after calling the start() method, the state of Thread becomes RUNNABLE, but this time the run() method is not necessarily executed, because the execution of the thread needs CPU time slice.
Only when the CPU time slice is obtained is the running state in the operating system. When everything is ready, that is, when waiting for the CPU time slice, it is called the ready state.
However, in the Java thread class, the running state and ready state of the operating system are represented by the RUNNABLE state. This is different from the state of the operating system.
Verification Code:
public class TestThreadState { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(); thread.start(); System.out.println("The status of the thread is:" + thread.getState()); } }
The operation result is:
The status of the thread is: RUNNABLE
3. TERMINATED
After the thread task is executed, the state will become terminated. Whether the end is because the method is executed or an exception is thrown in the middle and is not caught, it is a termination state.
Verification Code:
public class TestThreadState { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(); thread.start(); // After the thread is executed, the status changes to terminated Thread.sleep(100); System.out.println("The status of the thread is:" + thread.getState()); // The exception thrown during operation is not caught, and the status changes to terminated Thread exceptionThread = new Thread(() -> { int i = 1 / 0; }); exceptionThread.start(); Thread.sleep(100); // Sleep for 0.1 seconds, etc System.out.println("exceptionThread The status of the thread is:" + exceptionThread.getState()); } }
The operation result is:
The status of the thread is: TERMINATED Exception in thread "Thread-1" java.lang.ArithmeticException: / by zero at com.wang.thread.TestThreadState.lambda$main$0(TestThreadState.java:17) at java.base/java.lang.Thread.run(Thread.java:833) exceptionThread The status of the thread is: TERMINATED
4. TIMED_WAITING time limited waiting
The operations that can make the thread enter this state are:
- Thread.sleep(...) method
- Object.wait(): monitor lock of preemptive object with time limit
- Thread.join(): thread merge with time limit
- LockSupport.parkNanos(): lets the thread wait, in nanoseconds
- LockSupport.parkUntil(): lets the thread wait, and the time can be set flexibly
public class TestTimedWaitingState { public static void main(String[] args) throws InterruptedException { Thread demo = new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); demo.start(); // Sleep for 10 milliseconds and wait for the thread to start Thread.sleep(10); System.out.println("sleep When the thread status is:" + demo.getState()); } }
Operation results:
sleep When the thread status is: TIMED_WAITING