Some properties of Java threads: thread state, thread scheduling, etc

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:

  1. 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
  2. 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:

  1. Thread.sleep(...) method
  2. Object.wait(): monitor lock of preemptive object with time limit
  3. Thread.join(): thread merge with time limit
  4. LockSupport.parkNanos(): lets the thread wait, in nanoseconds
  5. 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

Keywords: Java thread

Added by Acs on Sun, 06 Mar 2022 04:07:23 +0200