Notes on Java threads -- Zhang Hongbo's zero foundation easy learning java

Posted by dmb on Mon, 27 Dec 2021 15:00:33 +0100

catalogue

1.3 thread status

background

1. Creation status

2. Operable state

3. Inoperable state

4. State of death

1.4 thread scheduling

1.5 thread priority

1.6 daemon thread

​​​​​​​

1.3 thread status

background

Threads have four states: creation state, runnable state, non runnable state and death state.

1. Creation status

After instantiating a thread object, the thread is in the creation state. The system does not allocate resources to threads in the creation state.

2. Operable state

When the thread object calls the run() method, the thread is in a runnable state. A thread in a runnable state for which the system has allocated the required system resources. Here, pay attention to distinguish between runnable and runnable. After the thread object calls the run() method, it only indicates that the thread is in a runnable state, not running. Usually, because the computer has only one CPU, only one thread in the runnable state can run at the same time. The purpose of sharing CPU can be achieved through the scheduling of Java running system. There may be multiple threads running at the same time, but there is only one running thread.

3. Inoperable state

Non runnable state is also called blocking state. For some reason, the system cannot execute the thread. In this case, even if the CPU is idle, the thread cannot be executed.

The reason why the thread becomes non running may be that the sleep() method, suspend() method, wait() method are called, or thread blocking occurs in the input / output stream.

4. State of death

When the thread finishes executing or calls the stop() method, it will enter the dead state.

The methods called by Java threads in different states and transitions between states are shown in the figure below:

1.4 thread scheduling

Java provides a thread scheduler to schedule all threads that enter the runnable state after the program is started. The thread scheduler determines the running order of the runnable threads according to the priority of the threads.

Thread scheduling is preemptive scheduling, that is, if a higher priority thread enters the runnable state during the current thread running process, the thread will be scheduled to run immediately.

Preemptive scheduling is divided into time slice mode and exclusive mode.

  • Time slice method: after the current active thread runs the current time slice, if there are other threads with the same priority in the ready state, the system will give the running right to other threads with the same priority in the ready state; The current active thread is transferred to the waiting queue to wait for the scheduling of the next time slice.
  • Exclusive mode: once the current active thread obtains the running right, it will continue to execute until the execution is completed, or the CPU is voluntarily abandoned for some reason, or the thread with high priority is in the runnable state.

The reason why a thread voluntarily abandons the CPU may be:

  1. The thread called the yield() or sleep() method and voluntarily gave up
  2. The thread called the wait() method
  3. Because the current thread performs I/O access, external memory read-write, waiting for user input and other operations, the thread is blocked

1.5 thread priority

Threads have 10 priorities, which are represented by 1 ~ 10 from low to high, and the default value is 5 Three static variables are defined in the thread class, as follows:

In addition, priority can be operated through two methods of the Thread class.

Examples of thread execution effects with three different priorities:

/**
 * @author asus
 */
public class PriorityDemo01 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 5;i++) {
            try{
                Thread.sleep(500);
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "function, i=" + i);
        }
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new PriorityDemo01(),"Thread 1");
        Thread t2 = new Thread(new PriorityDemo01(),"Thread 2");
        Thread t3 = new Thread(new PriorityDemo01(),"Thread 3");
        t1.setPriority(Thread.MIN_PRIORITY);
        t2.setPriority(Thread.NORM_PRIORITY);
        t3.setPriority(Thread.MAX_PRIORITY);
        t1.start();
        t2.start();
        t3.start();
    }
}

The execution results are:

From the running results, the running order of threads will be determined according to their priority. However, it should be noted that the higher the thread is, the higher the thread will not run first. The thread running is determined by the CPU scheduling.

When a Java program starts running, the JVM will automatically create a thread called the main thread.

The importance and particularity of the main thread are shown in the following two aspects:

  1. Is a thread that produces other threads
  2. Usually, various closing operations are performed, which is the last one

Although the main Thread does not need to be created manually, it is still an object of Thread class. The reference of the main Thread can be obtained through the method of Thread class, so as to achieve the purpose of operating the main Thread.

The basic information examples of main thread are:

/**
 * @author asus
 */
public class GetMainThread {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println("Of the current main thread ID Yes: " + thread.getId());
        System.out.println("The name of the current main thread is:" + thread.getName());
        System.out.println("The priority of the current primary and secondary processes is:" + thread.getPriority());
        System.out.println("When the thread group of its main thread is:" + thread.getThreadGroup().getName());
    }
}

The execution results are:

The above code shows that the priority of the main thread is NORM_PRIORITY

The comity instance of the program, that is, the yield() method is used to temporarily transfer the operation of one thread to other threads for execution:

/**
 * @author asus
 */
public class PriorityDemo02 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 5;i++) {
            System.out.println(Thread.currentThread().getName() + "function, i=" + i);
            if(i == 3){
                System.out.println("Thread comity:");
                Thread.yield();
            }
        }
    }

    public static void main(String[] args) {
        //Instantiate PriorityDemo02 object
        PriorityDemo02 my = new PriorityDemo02();
        Thread t1 = new Thread(my,"Thread 1");
        Thread t2 = new Thread(my,"Thread 2");
        t1.start();
        t2.start();
    }
}

The execution results are:

It can be found from the results that when the thread meets the condition (i==3), this thread will pause and let other threads run first.  

1.6 daemon thread

Threads are all non daemon threads by default, and non daemon threads are also called user threads. When all user threads end, the daemon thread ends immediately. Because the daemon thread will end at any time, the work done by the daemon thread should end at any time without affecting the running results.

Note: daemon thread is often used in Java thread application development.

Set the Thread as a daemon by calling the method of the Thread class

public final void setDaemon(boolean on)

example:

First, construct a thread class that simulates playing music

public static class MusicThread extends Thread {
        @Override
        public void run() {
            while (true) {
                System.out.println("Music playing......");
                try{
                    sleep(100);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

Then construct a thread class that simulates the installer

public static class InstallThread extends Thread {
        @Override
        public void run() {
            System.out.println("Installation starts");
            for (int i = 0; i <= 100;i=i+10) {
                System.out.println("already installed" + i + "%");
                try {
                    sleep(100);
                } catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        }

Finally, the main method is constructed to call two threads

public static void main(String[] args) {
        MusicThread music = new MusicThread();
        music.setDaemon(true);
        music.start();
        InstallThread install = new InstallThread();
        install.start();
    }

The results are as follows:

In this example, if the thread simulating playing music runs alone, it will not stop and the concert will be played all the time. However, with the daemon thread, once the simulation installation thread ends as a user thread, the simulation music playing thread will also end immediately.

Topics: Java intellij-idea