为什么使用start方法启动Java的Thread线程?
一、简介
在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线程?相关推荐
- 【java】Thread.start 它是怎么让线程启动的呢
1.概述 转载:面经手册 · 第19篇<Thread.start() ,它是怎么让线程启动的呢?> 可悲可叹,这个问题,6年了,我才第一次知道. 线程启动分析 new Thread(() ...
- Java学习笔记----线程
继续学习----------------------------------------------------------------------- 在Java中线程指的是两件事 1)java.la ...
- 【java】java多线程及线程池详解
目录 前言 线程是什么?多线程是什么? 多线程的作用和好处以及缺点 守护线程和用户线程 并发和并行的区别 一.线程的状态和常用方法 1.线程各种状态转化图 2.线程相关常用方法有 ① wait() ② ...
- Java中Thread类的start()和run()方法
1.两个方法的区别 start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法.start()不能被重复调用. run() : run()就和普通的成员方法一样,可以被重复调用 ...
- java new thread参数_java开启新线程并传参的两种方法
一.继承Thread类 步骤: 1):定义一个类A继承于Java.lang.Thread类. 2):在A类中覆盖Thread类中的run方法. 3):我们在run方法中编写需要执行的操作:run方法里 ...
- java的Thread类start0方法源码
带着几个问题去看源码 1.如何找到native方法的源码 2.Java的Thread对象.JavaThread.OSThread.操作系统线程 3.Java线程与操作系统线程的关联 4.Java线程保 ...
- java setdaemon_Java Thread setDaemon()方法
Thread类的setDaemon()方法用于将线程标记为守护程序线程或用户线程. 它的生命依赖于用户线程,即当所有用户线程都消亡时,JVM会自动终止该线程.必须在线程启动之前调用它. 如果在声明线程 ...
- java中如何启动一个新的线程三种方法
java开启新线程的三种方法: 方法1:继承Thread类 1):定义bai一个继承自Java.lang.Thread类的du类A. 2):覆盖zhiA类Thread类中的run方法. 3):我们编写 ...
- java threadgourp_Java Thread getThreadGroup()方法
Java Thread getThreadGroup()方法 java.lang.Thread.getThreadGroup() 方法返回此线程所属的线程组.它返回null,如果该线程已经死亡(停止) ...
最新文章
- 开启Windows8里面的Hyper-V虚拟机功能
- YTKNetwork源码详解
- Axure下拉框级联操作
- java内存溢出排查top_process-parse-shell
- sqlserver 登录失败——孤立用户
- 10个最常见的 HTML5 面试题及答案
- 前端----JQuery
- 钢结构计算机模拟拼装,钢结构技术-钢结构虚拟预拼装技术
- Adadelta理解
- 如何用计算机做牛顿迭代公式,牛顿迭代法
- 谈程序猿的技术能力(Technology)和工程能力(Engineering)
- 面试须知的前端渲染和后端渲染
- 怎样隐藏Android软件盘
- 利用python画钻石_用Python制作钻石ASCII艺术品
- map和multimap的用法详解
- 计算机科学家格言,未来科技有关名言
- 用navicat访问linux数据库,成功实现Navicat访问Linux中安装的MySQL数据库
- 【机器学习】HMM模型
- 云计算主要学些什么技术内容?零基础能学会吗?
- Linux运维管理的必备工具
热门文章
- CVPR 2022 Oral | 人大高瓴AI学院提出:面向动态视音场景的问答学习机制
- 星级评价的代码php,JavaScript_使用jQuery实现星级评分代码分享,前面有一篇原生js实现星级评 - phpStudy...
- 【poj3311】Hie with the Pie
- matlab tif dpi,轻松解决杂志要求的300dpi分辨率、TIFF格式图片
- PUE 1.2,总投资达36.4亿,17600个机柜!天和防务拟建陕西最大数据中心
- mysql周报内容范文_mysql 数据分析如何实现日报、周报、月报和年报?
- Windows10 系统部分软件字体虚化不清晰
- 你若安好便是晴天_百度百科
- Buy and Resell HDU - 6438 贪心
- 线程初步(四)--小练习