Code demonstration:
/** * <p> * start() 和 run() 的比较 * </p> * * @author 踏雪彡寻梅 * @version 1.0 * @date 2020/9/20 - 16:15 * @since JDK1.8 */public class StartAndRunMethod { public static void main(String[] args) { // run 方法演示 // 输出: name: main // 说明由主线程去执行的, 不符合新建一个线程的本意 Runnable runnable = () -> { System.out.println("name: " + Thread.currentThread().getName()); }; runnable.run(); // start 方法演示 // 输出: name: Thread-0 // 说明新建了一个线程, 符合本意 new Thread(runnable).start(); } }复制代码
From the above example The following two points can be analyzed:
Directly using the run
method will not start a new thread. (wrong way)
start
method starts a new thread. (Correct way)
start
method can start a new thread.
start
method after initialization, the current thread (usually the main thread) will request the JVM virtual machine to start this if it is free. New thread. start
method, we may not be able to start the thread immediately. srtart
method is called, it does not mean that this method has started running. It may not run until later, or it may not run for a long time, such as in case of starvation. start
method, and then thread 2 calls the start
method, only to find that thread 2 first The situation of execution after executing thread 1. start
method is called does not determine the order in which the actual threads are executed. start
method will involve two threads. start
method, the second one is the new one the rout. start
is already executed by the child thread. This statement is actually the main thread or the main thread. It is executed by the parent thread, and a new thread is created after it is executed. start
Method to create a new thread preparations
run
method. code. Note: The start method cannot be executed repeatedly
Code example
/** * <p> * 演示不能重复的执行 start 方法(两次及以上), 否则会报错 * </p> * * @author 踏雪彡寻梅 * @version 1.0 * @date 2020/9/20 - 16:47 * @since JDK1.8 */public class CantStartTwice { public static void main(String[] args) { Runnable runnable = () -> { System.out.println("name: " + Thread.currentThread().getName()); }; Thread thread = new Thread(runnable); // 输出: name: Thread-0 thread.start(); // 输出: 抛出 java.lang.IllegalThreadStateException // 即非法线程状态异常(线程状态不符合规定) thread.start(); } }复制代码
Cause of error
start
Once execution starts, the thread state will enter the subsequent state from the initial New state, such as Runnable, and then Once the thread completes execution, the thread will become a terminated state, and the terminated state can never be returned, so the above exception will be thrown, which means that it cannot return to the initial state. The description here is not clear enough. Let's take a look at the source code to understand more thoroughly. public synchronized void start() { /** * 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". */ // 第一步, 检查线程状态是否为初始状态, 这里也就是上面抛出异常的原因 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. */ // 第二步, 加入线程组 group.add(this); boolean started = false; try { // 第三步, 调用 start0 方法 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 */ } } }复制代码
Step one: When starting a new thread, it will first check whether the thread state is the initial state, which is also the reason why the above exception is thrown. That is, the following code:
if (threadStatus != 0) throw new IllegalThreadStateException();复制代码
Among them, threadStatus
The annotation of this variable is as follows, which means that the Java thread status is initially expressed as 0 (not yet started):
/* Java thread status for tools, * initialized to indicate thread 'not yet started' */private volatile int threadStatus = 0;复制代码
Step 2:Add it to the thread group. That is, the following code:
group.add(this);复制代码
The third step:Finally call start0()
This native method (native means that its code is not implemented by Java, but by C/C implementation, the specific implementation can be seen in the JDK, just understand it), that is, the following code:
boolean started = false;try { // 第三步, 调用 start0 方法 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 */ } }复制代码
@Overridepublic void run() { // 传入了 target 对象(即 Runnable 接口的实现), 执行传入的 target 对象的 run 方法 if (target != null) { target.run(); } }复制代码
The first one: Overriding the run
method of the Thread
class, Thread
's run
method will be invalid, and the overridden run
method will be executed.
Second type: Pass in the target
object (that is, the implementation of the Runnable
interface) and execute the original # of Thread
The ##run method then proceeds to execute the
run method of the
target object.
method is an ordinary method. The
run method is directly executed above. It is equivalent to executing the ordinary method we wrote ourselves, so its execution thread is our main thread.
method directly, but you must call the
start method, in which you can call
run## indirectly. # method.
Related learning recommendations:
The above is the detailed content of A closer look at the right and wrong ways to start threads in Java. For more information, please follow other related articles on the PHP Chinese website!