A detailed analysis of the right and wrong ways to start a thread in Java

These reviews

  1. How many ways are there to implement multithreading in Java? (In essence)

Comparison of the start method and the run method

Code demo:

/** * <p> * Comparison of start() and run() * </p> **@authorSnow's looking for mei *@version 1.0
 * @date2020/9/20-16:15 *@sinceJDK1.8 * /
public class StartAndRunMethod {
    public static void main(String[] args) {
        // run method demo
        // Output: name: main
        // the main thread does not meet the purpose of creating a new thread
        Runnable runnable = () -> {
            System.out.println("name: " + Thread.currentThread().getName());
        };
        runnable.run();

        // start method demo
        // Output: name: thread-0
        // Create a new thread
        newThread(runnable).start(); }}Copy the code

Two points can be drawn from the above examples:

  • Using the run method directly does not start a new thread. (Wrong way)

  • The start method starts a new thread. (Correct way)

Start method analysis

Start method meaning and precautions

  • The start method starts a new thread.

    • After the start method is called on a thread object after initialization, the current thread (usually the main thread) asks the JVM to start the new thread if it is free.

    • That is, the essence of starting a new thread is to ask the JVM to run it.

    • It is not simply up to us to decide when the thread will run, but up to the thread scheduler.

    • If it is busy, even if we run the start method, we may not be able to start the thread immediately.

    • So saying that the srtart method has been called does not mean that the method has started to run. It may not work until later, or it may not work for a long time, for example in the case of starvation.

    • If thread 1 calls the start method first, thread 2 calls the start method and thread 2 executes thread 1.

    • Conclusion: The order in which the start method is called does not determine the order in which the actual threads execute.

    • Matters needing attention

      • The start method involves two threads.

      • The first is the main thread, because we must have a main thread or another thread (even if it is not the main thread) to execute the start method, and the second is the new thread.

      • In many cases, the main thread that created the thread for us is ignored. Do not mistake the start call for the child thread to execute the statement. This statement is actually executed by the main thread, or the parent thread, before creating a new thread.

  • The start method prepares to create a new thread

    • First, it puts itself in a state of readiness.

      • Ready state means that other resources other than CPU have been obtained, such as context, stack, thread state, and PC(PC is a register, PC points to the running position of the program).
    • Once you’ve done that, you’re all set except for the east wind, which is CPU resources.

    • After the preparation is done, the thread can be further scheduled by the JVM or the operating system to the execution state to wait for CPU resources, and then actually enter the run state to execute the code in the run method.

  • Note: Do not execute the start method repeatedly

    • Code sample

      /** * <p> * The start method cannot be repeated (twice or more), otherwise an error will be reported * </p> **@authorSnow's looking for mei *@version 1.0
      * @date2020/9/20 - yet *@sinceJDK1.8 * /
      public class CantStartTwice {
          public static void main(String[] args) {
              Runnable runnable = () -> {
                  System.out.println("name: " + Thread.currentThread().getName());
              };
              Thread thread = new Thread(runnable);
              // Output: name: thread-0
              thread.start();
              / / output: throw Java. Lang. IllegalThreadStateException
              // The thread status is abnormal.thread.start(); }}Copy the code
    • The reason for the error

      • startOnce execution starts, the thread goes from the initial New state to a subsequent state, such as Runnable, and then, once the thread is finished, it goes to a terminated state. The terminated state can never be returned, so the above exception is thrown, meaning that it cannot return to the original state. The description here is not clear enough, let’s look at the source code to understand more clearly.

Start method source code analysis

The source code

public synchronized void start(a) {
    /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */
    // Check whether the thread is in its initial state, which is why the above exception was thrown
    if(threadStatus ! =0)
        throw new IllegalThreadStateException();

    /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */
    // Join the thread group
    group.add(this);

    boolean started = false;
    try {
        // Call the start0 method
        start0();
        started = true;
    } finally {
        try {
            if(! started) { group.threadStartFailed(this); }}catch (Throwable ignore) {
            /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */}}}Copy the code

Flow in source code

Step 1: Starting a new thread checks whether the thread is in its original state, which is why the above exception was thrown. The following code:

if(threadStatus ! =0)
	throw new IllegalThreadStateException();
Copy the code

ThreadStatus = 0; threadStatus = 0; threadStatus = 0;

/* Java thread status for tools, * initialized to indicate thread 'not yet started' */
private volatile int threadStatus = 0;
Copy the code

Step 2: Add it to the thread group. The following code:

group.add(this);
Copy the code

Step 3: Finally call the start0() native method (native means its code is not implemented by Java, but by C/C++, the specific implementation can be seen in JDK, understand it), namely the following code:

boolean started = false;
try {
    // Call the start0 method
    start0();
    started = true;
} finally {
    try {
        if(! started) { group.threadStartFailed(this); }}catch (Throwable ignore) {
        /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */}}Copy the code

Analysis of RUN method

Run method source code analysis

@Override
public void run(a) {
    // The target object (the implementation of the Runnable interface) is passed in and the run method of the target object is executed
    if(target ! =null) { target.run(); }}Copy the code

There are two cases for the run method

  • If a Thread’s run method is overridden, the Thread’s run method will become invalid and the overridden run method will be executed.

  • Second, we pass in a target object (the implementation of the Runnable interface), execute the original run method of Thread, and then execute the run method of the target object.

  • Conclusion:

    • The run method is a normal method, and executing the run method directly is equivalent to executing the normal method we wrote, so its thread of execution is our main thread.

    • So to actually start a thread, you don’t call the run method directly, you call the start method, which can call the run method indirectly.


If there is insufficient writing, please forgive me, please give more advice.

My personal blog website:www.xilikeli.cnWelcome to visit (#.#)

And welcome to mineMaking the home page, my personal blog has been open source, interested partners can dot star, thank you (#.#)