聊一聊多线程的 run() 和 start(),挖一挖start0

简介: 聊一聊多线程的 run() 和 start(),挖一挖start0

首先是结论,应该大家知道:


调用start() 会触发多线程执行 ;

调用run() 还是当做执行了一个普通方法,没有多线程执行。


start()示例:


public class MyThread extends Thread {
    @SneakyThrows
    @Override
    public void run(){
        sleep(5000);
        System.out.println("run 内容打印 ");
    }
    public static void main(String[] args) {
        System.out.println("start 调用");
        MyThread testThread1=new MyThread();
        new Thread(testThread1,"线程1").start();
        System.out.println("主线程 最后的输出");
    }
}



结果:


image.png


run()示例:


public class MyThread extends Thread {
    @SneakyThrows
    @Override
    public void run(){
        sleep(5000);
        System.out.println("run 内容打印 ");
    }
    public static void main(String[] args) {
        System.out.println("run 调用");
        MyThread testThread2=new MyThread();
        new Thread(testThread2,"线程2").run();
        System.out.println("主线程 最后的输出");
    }
}



结果:


image.png


也就是咱们在使用多线程的时候要注意,调用run()是不正确的,不是我们想要的多线程效果。


那么我们应该调用 start() 。


我想问, 为什么?


为什么调用  start() 就是多线程  ?


ok,进入这篇文章的主题,一起挖源码 。


先看看java里面 start()的源码注释 :


使该线程开始执行;Java虚拟机 调用此线程的  run 方法。


结果是两个线程同时运行:


当前线程 start 和另一个线程(执行其运行方法)。


不用多说,大概也是告诉我们这个方法调用之后,是会触发多线程执行。


image.png 


再看看start方法,里面调用了 start0() ,然后没了。


image.png


那么可以知道 关键在于  start0() 。


可以看到这个start0 方法被 native 修饰着 。


native 关键字告诉编译器(其实是JVM)调用的是该方法在外部定义,这里指的是C。


也就是说光看java的源码是没办法找到 start0 ()的。


没事,既然进到我的文章,绝不会就此结束 。


openJDK源码 在线查阅地址 :


jdk8/jdk8/jdk: 687fd7c7986d /src/


锁定Thread.c


image.png


来看看我们想找的相关源码,发现目标 start0:


image.png


在这里大致能知道,调用的是JVM的StartThread函数 。


也就是说我们需要去挖JVM的代码 ,Java 8, 使用的是 Oracle 的64位HotSpot虚拟机。


所以我直接下载HotSpot 源码。


锁定HotSpot 源码 :


找源码的过程我就省略了, 给出一些核心点,


可以看到里面 调用了 JavaThread :


image.png再看看 JavaThread  :


看到这里,基本就差不多了锁定了 真的新创建了一个线程   create_thread


image.png大致就挖到这吧。可能这篇文章对大家帮助不大,但是对于跟我一样看源码有强迫症的人,多多少少心里会舒坦一些哈哈。

相关文章
|
2月前
|
存储 Java 程序员
优化Java多线程应用:是创建Thread对象直接调用start()方法?还是用个变量调用?
这篇文章探讨了Java中两种创建和启动线程的方法,并分析了它们的区别。作者建议直接调用 `Thread` 对象的 `start()` 方法,而非保持强引用,以避免内存泄漏、简化线程生命周期管理,并减少不必要的线程控制。文章详细解释了这种方法在使用 `ThreadLocal` 时的优势,并提供了代码示例。作者洛小豆,文章来源于稀土掘金。
【多线程面试题 三】、 run()和start()有什么区别?
run()方法定义线程执行的任务,而start()方法启动线程,使得run()在新的线程中异步执行;直接调用run()方法只会同步执行run()中的代码,不会创建新线程。
|
6月前
|
安全 Java
【JAVA】线程的run()和start()有什么区别?
【JAVA】线程的run()和start()有什么区别?
|
6月前
|
安全 Java
面试官:线程调用2次start会怎样?我支支吾吾没答上来
面试官:线程调用2次start会怎样?我支支吾吾没答上来
33 1
|
Java 调度
start()方法和run()方法区别与多线程抢占式运行原理
我们通过一个例子来进行总结,我们写一个利用Thread创建的简单的多线程例子,然后分别执行start()与run()方法,执行结果如下所示:
92 0
|
6月前
|
Java
多线程中的run方法和start方法有什么区别?
多线程中的run方法和start方法有什么区别?
|
安全 Java API
为什么启动线程不直接调用run(),而要调用start(),如果调用两次start()方法会有什么后果
1位工作6年的小伙伴去某里P6一面,被问到这样一道面试题,说,为什么启动一个线程不直接调用run()方法,而要调用start()方法来启动,如果调用两次start()会有什么后果?
114 0
|
Java
Java线程中的run()和start()区别
Java线程中的run()和start()区别
87 0
|
1月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
44 1
C++ 多线程之初识多线程
|
26天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
19 3