一、简介

在Java代码当中,当我们需要开启子线程去处理一些任务的时候,往往是调用Thread对象的start方法,这样Thread实例中的Runnable对象的run方法就会在一个新的线程当中执行;

// 创建一个线程
Thread thread = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("working in " + Thread.currentThread().getName());}
});// 在什么线程调用,run方法的任务就在什么线程执行
thread.run();// 在一个新的线程中执行run方法中的任务
thread.start();

二、分析run()方法

如下代码可见,当我们直接调用run方法的时候,就相当于实例直接调用一个普通的方法一样,所以无论我们在什么线程中调用run方法,run方法中的业务就在什么线程执行,并不会说启动一个新的线程去执行run方法中的任务;

// Thread.class中的run方法,target为Runnable实例
@Override
public void run() {if (target != null) {target.run();}
}

三、分析start()方法

如下我们直接来看Thread.class中的代码;

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. */// 1. 将当前线程实例添加到ThreadGroup对象group中group.add(this);boolean started = false;try {// 2. 调用native方法start0()start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}}
}// native 方法
private native void start0();

看上面代码的注释1那里,我们来看下Thread.class代码里面group是哪里来的

private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {if (name == null) {throw new NullPointerException("name cannot be null");}this.name = name;Thread parent = currentThread();// 1. 从System类中获取安全管理器SecurityManager security = System.getSecurityManager();if (g == null) {/* Determine if it's an applet or not *//* If there is a security manager, ask the security managerwhat to do. */if (security != null) {// 2. 从安全管理器中过去ThreadGroup对象g = security.getThreadGroup();}/* If the security doesn't have a strong opinion of the matteruse the parent thread group. */if (g == null) {g = parent.getThreadGroup();}}g.addUnstarted();this.group = g;// 省略一部分代码···
}

从上面注释1,2可以看出,Thread实例中的ThreadGroup实例g主要是从底层代码中获取的,即group.add(this)执行之后,将当前线程传给了底层系统去管理

下面看下start0()方法,因为start0()方法为Native方法,看下是怎么实现的,如下为src/main/native/Thread.c的代码

static JNINativeMethod methods[] = {// 从这里我们可以看到start0方法主要JVM_StartThread的一个方法引用{"start0",           "(JZ)V",      (void *)&JVM_StartThread},{"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},{"yield",            "()V",        (void *)&JVM_Yield},{"sleep",            "(Ljava/lang/Object;J)V",       (void *)&JVM_Sleep},{"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},{"interrupt0",       "()V",        (void *)&JVM_Interrupt},{"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},{"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},{"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};

下面一下JVM_StartThread的情况

// 如下为/openjdkjvm/OpenjdkJvm.cc中的代码
JNIEXPORT void JVM_StartThread(JNIEnv* env, jobject jthread, jlong stack_size, jboolean daemon) {art::Thread::CreateNativeThread(env, jthread, stack_size, daemon == JNI_TRUE);
}// 如下为/runtime/thread.cc中创建native线程的代码
void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) {···// 这里就不做展开了
}

总结:从上面代码可以看出,Thread调用start的时候,将thread实例传给虚拟机持有,然后调用native创建一个新的线程,由虚拟机进行调度。

水平有限,有误请指正!

为什么使用start方法启动Java的Thread线程?相关推荐

  1. 【java】Thread.start 它是怎么让线程启动的呢

    1.概述 转载:面经手册 · 第19篇<Thread.start() ,它是怎么让线程启动的呢?> 可悲可叹,这个问题,6年了,我才第一次知道. 线程启动分析 new Thread(() ...

  2. Java学习笔记----线程

    继续学习----------------------------------------------------------------------- 在Java中线程指的是两件事 1)java.la ...

  3. 【java】java多线程及线程池详解

    目录 前言 线程是什么?多线程是什么? 多线程的作用和好处以及缺点 守护线程和用户线程 并发和并行的区别 一.线程的状态和常用方法 1.线程各种状态转化图 2.线程相关常用方法有 ① wait() ② ...

  4. Java中Thread类的start()和run()方法

    1.两个方法的区别 start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法.start()不能被重复调用. run()   : run()就和普通的成员方法一样,可以被重复调用 ...

  5. java new thread参数_java开启新线程并传参的两种方法

    一.继承Thread类 步骤: 1):定义一个类A继承于Java.lang.Thread类. 2):在A类中覆盖Thread类中的run方法. 3):我们在run方法中编写需要执行的操作:run方法里 ...

  6. java的Thread类start0方法源码

    带着几个问题去看源码 1.如何找到native方法的源码 2.Java的Thread对象.JavaThread.OSThread.操作系统线程 3.Java线程与操作系统线程的关联 4.Java线程保 ...

  7. java setdaemon_Java Thread setDaemon()方法

    Thread类的setDaemon()方法用于将线程标记为守护程序线程或用户线程. 它的生命依赖于用户线程,即当所有用户线程都消亡时,JVM会自动终止该线程.必须在线程启动之前调用它. 如果在声明线程 ...

  8. java中如何启动一个新的线程三种方法

    java开启新线程的三种方法: 方法1:继承Thread类 1):定义bai一个继承自Java.lang.Thread类的du类A. 2):覆盖zhiA类Thread类中的run方法. 3):我们编写 ...

  9. java threadgourp_Java Thread getThreadGroup()方法

    Java Thread getThreadGroup()方法 java.lang.Thread.getThreadGroup() 方法返回此线程所属的线程组.它返回null,如果该线程已经死亡(停止) ...

最新文章

  1. 开启Windows8里面的Hyper-V虚拟机功能
  2. YTKNetwork源码详解
  3. Axure下拉框级联操作
  4. java内存溢出排查top_process-parse-shell
  5. sqlserver 登录失败——孤立用户
  6. 10个最常见的 HTML5 面试题及答案
  7. 前端----JQuery
  8. 钢结构计算机模拟拼装,钢结构技术-钢结构虚拟预拼装技术
  9. Adadelta理解
  10. 如何用计算机做牛顿迭代公式,牛顿迭代法
  11. 谈程序猿的技术能力(Technology)和工程能力(Engineering)
  12. 面试须知的前端渲染和后端渲染
  13. 怎样隐藏Android软件盘
  14. 利用python画钻石_用Python制作钻石ASCII艺术品
  15. map和multimap的用法详解
  16. 计算机科学家格言,未来科技有关名言
  17. 用navicat访问linux数据库,成功实现Navicat访问Linux中安装的MySQL数据库
  18. 【机器学习】HMM模型
  19. 云计算主要学些什么技术内容?零基础能学会吗?
  20. Linux运维管理的必备工具

热门文章

  1. CVPR 2022 Oral | 人大高瓴AI学院提出:面向动态视音场景的问答学习机制
  2. 星级评价的代码php,JavaScript_使用jQuery实现星级评分代码分享,前面有一篇原生js实现星级评 - phpStudy...
  3. 【poj3311】Hie with the Pie
  4. matlab tif dpi,轻松解决杂志要求的300dpi分辨率、TIFF格式图片
  5. PUE 1.2,总投资达36.4亿,17600个机柜!天和防务拟建陕西最大数据中心
  6. mysql周报内容范文_mysql 数据分析如何实现日报、周报、月报和年报?
  7. Windows10 系统部分软件字体虚化不清晰
  8. 你若安好便是晴天_百度百科
  9. Buy and Resell HDU - 6438 贪心
  10. 线程初步(四)--小练习