Analysis of Thread class source code

Thread is a very important class for multithreading problems in interviews. Let's take a look at what weird things are in the Thread class and how to answer various difficult questions from interviewers.

Thread use

Thread name

When using multithreading, the commonly used method is to set and view the scene name, namely setName(String name) and getName().

By default, the name of the main thread is main, and the names of other threads are Thread-x, where x represents the number of threads. The reason depends on its construction method

public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}

We can see that it calls the init method, which calls the nextThreadNum method internally. This method is a thread-safe method, and only one thread can modify it at the same time. And threadInitNumber is a static variable, it can be accessed by all objects in the class, so each thread directly +1 as the child thread suffix when it is created.

Thread priority

The priority of the thread can be understood as the probability of the thread preempting the CPU time slice. The higher the priority, the greater the probability of acquisition, but it does not mean that the higher priority must be executed first.

The default priority is 5, and the maximum value is 10 and the minimum value is 1.

So how to ensure the order of thread execution?

  • You can use the join() method

Thread.join() joins the specified thread to the current thread, and can merge two alternately executed threads into sequential execution threads. For example, the Join() method of thread A is called in thread B, and thread B will not continue to execute until thread A has finished executing.

Daemon thread

The daemon thread is very humble by its name. The daemon thread is a low-priority thread dedicated to serving other threads. After other threads are executed, they will exit together with the JVM. The garbage collection thread is a typical daemon thread.

main feature

  • When other non-daemon threads finish executing, the virtual machine will exit and the daemon thread will be stopped
  • The daemon thread is a service thread, there is no need to continue running without a service object
  • The daemon thread should not access shared resources, because it may hang at any time
  • The new thread spawned in the daemon thread is also a daemon thread

The daemon thread can be set by setDaemon.

public final void setDaemon(boolean on) {
    // 判断是否有权限
    checkAccess();
    // 判断是否活跃
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    daemon = on;
}

It can be known from the source code that the target thread must be set as a daemon thread before the thread is started, otherwise an error will be reported.

The difference between start() and run()

It's a common interview question, but it's also very easy to confuse

  • What is defined in the run method is the task logic executed by the thread , and it is no different from ordinary methods.
  • The start method starts the thread, turns the thread from the NEW state to RUNNABLE , and then the jvm calls the run () method of the thread to perform the task
  • The start method cannot be called multiple times, otherwise java.lang.IllegalStateException will be thrown; and the run () method can be called multiple times because it is a normal method

The JVM executes the start method, and another thread executes the run method in the thread, which can play a multi-threaded role. If the run method in the thread is directly called, then it is still in the main thread and does not have the effect of multi-threading.

sleep method

  • Sleep for the specified number of milliseconds, during which time the lock is not released
  • If the parameter is illegal, throw an IllegalArgumentException
  • In the sleep state, the signal can be interrupted accordingly, and an InterruptedException will be thrown

How to stop the thread properly

The first thing to be clear is not to use the stop() method. It is too violent. If the thread is not given enough time to process the logic of saving data before the thread stops, the task will stop, which will cause data integrity problems.

In general, the interrupt method is used to request to stop the thread. It is much milder than stop. It just sends a signal to the thread to tell him that it should end, and then the thread decides how to stop and whether or not according to its own business logic stop.

There are four key points in the interrupt method

  • You can only interrupt yourself, otherwise a SecurityException will be thrown
  • If the thread calls wait, sleep, join and other methods into blocking, it will cause the interruption of the call to be invalid and throw an InterruptedException.
  • When the above situation does not happen, the thread's interruption status will be changed.
  • It is invalid to interrupt a thread that has hung up.

In addition, the methods related to interruption in java are interrupted() and isInterrupted()

  • isInterrupted () is used to determine the interrupt flag bit, the call will not affect the current flag bit
  • interrupted () is used to clear the interrupt flag bit, the call will clear the flag bit

yield method

Looking at the source code of Thread, you can know that the yield() method is a local method. Realized by C or C++. It is unstable.

The current thread calls yield() to give up the right to use the CPU for execution by other threads, but it is not guaranteed to give up, whoever grabs the CPU first will execute it first

The current thread calls the yield() method, which will change the state from RUNNABLE to WAITING

join method

Calling the join method will wait for the execution of the thread to complete before executing other threads. This method can be used to implement the orderly execution of threads.

The bottom layer is still implemented through the wait() method

When the current thread terminates, the notifyAll method of the current instance will be called to wake up other threads

Calling the join method will change the current thread from the RUNNABLE state to the WAITING state.

Thread actual combat drill

Name the thread

  • Implemented Runnable to achieve multi-threading
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        //打印出当前线程的名字
        System.out.println(Thread.currentThread().getName());
    }
}
  • test
public class MyRunnableDemo {
    public static void main(String[] args) {
        // 创建MyRunnable类的对象
        MyRunnable my = new MyRunnable();
        // 使用带参构造方法给线程起名字
        Thread t1 = new Thread(my,"关注我");
        Thread t2 = new Thread(my,"冢狐");
        t1.start();
        t2.start();
        // 打印出当前线程的名字
        System.out.println(Thread.currentThread().getName());
    }
}
  • result

image

Daemon thread

  • Set up the daemon thread
public class MyRunnableDemo {
    public static void main(String[] args) {
        // 创建MyRunnable类的对象
        MyRunnable my = new MyRunnable();
        // 使用带参构造方法给线程起名字
        Thread t1 = new Thread(my,"关注我");
        Thread t2 = new Thread(my,"冢狐");
        //设置守护线程
        t2.setDaemon(true);
        t1.start();
        t2.start();
        // 打印出当前线程的名字
        System.out.println(Thread.currentThread().getName());
    }
}
  • result

image

After thread 1 and the main thread are executed, our daemon thread will not be executed, so we need to set up the daemon thread before starting

Thread stop

public class Main {
    public static void main(String[] args) {
        Main main=new Main();
        //创建线程并启动
        Thread t=new Thread(main.runnable);
        System.out.println("This is main");
        t.start();
        try {
            // 在main线程睡个三秒钟
            Thread.sleep(3000);
        }catch (InterruptedException e){
            System.out.println("In main");
            e.printStackTrace();
        }
        // 设置中断
        t.interrupt();
    }
    Runnable runnable=()->{
        int i=0;
        try {
            while (i<1000){
                // 睡个半秒再执行
                Thread.sleep(500);
                System.out.println(i++);
            }
        }catch (InterruptedException e){
            // 判断该阻塞线程是否还在
            System.out.println(Thread.currentThread().isAlive());
            // 判断该线程的中断标志位状态
            System.out.println(Thread.currentThread().isInterrupted());

            System.out.println("In Runnable");
            e.printStackTrace();
        }
    };
}
  • result

image

Description:

image

At last

  • If you feel that you are rewarded after reading it, I hope to give me a thumbs up. This will be the biggest motivation for me to update. Thank you for your support.
  • Welcome everyone to pay attention to my public account [Java Fox], focusing on the basic knowledge of java and computer, I promise to let you get something after reading it, if you don’t believe me, hit me
  • If you have different opinions or suggestions after reading, please comment and share with us. Thank you for your support and love.

——I am Chuhu, and I love programming as much as you.

image

Guess you like

Origin blog.csdn.net/issunmingzhi/article/details/111479120