zoukankan      html  css  js  c++  java
  • Java Thread之start和run方法的区别

    原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11421515.html

    start

    用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,run方法运行结束,此线程随即终止。

    start方法源码示例

    一个 Java 线程的创建本质上就对应了一个本地线程(native thread)的创建,两者是一一对应的。

    关键问题是:本地线程执行的应该是本地代码,而 Java 线程提供的线程函数(run)是 Java 方法,编译出的是 Java 字节码。

    所以, Java 线程其实提供了一个统一的线程函数,该线程函数通过 Java 虚拟机调用 Java 线程方法 , 这是通过 Java 本地方法 start0 调用来实现的。 

    也就是新创建的线程启动调用native start0方法,而这些native方法的注册是在Thread对象初始化的时候完成的

    Thread 类有个 registerNatives 本地方法,该方法主要的作用就是注册一些本地方法供 Thread 类使用,如 start0(),stop0() 等等,可以说,所有操作本地线程的本地方法都是由它注册的。

    这个方法放在一个 static 语句块中,当该类被加载到 JVM 中的时候,它就会被调用,进而注册相应的本地方法。(查看本地方法的源码需要前往 http://jdk.java.net/java-se-ri/8 下载openjdk的源代码)

    而本地方法 registerNatives 是定义在 Thread.c 文件中的。Thread.c 是个很小的文件,它定义了各个操作系统平台都要用到的关于线程的公用数据和操作,如下: 

    可以看出 Java 线程调用 start->start0 的方法,实际上会调用到 JVM_StartThread 方法,而 JVM_StartThread 最终调用的是 Java 线程的 run 方法。

    在 jvm.cpp 中,有如下代码段:

    这里 JVM_ENTRY 是一个宏,用来定义 JVM_StartThread 函数,可以看到函数内创建了真正的平台相关的本地线程,其线程函数是 thread_entry,如下:

    可以看到调用了 vmSymbols::run_method_name 方法,而 run_method_name 是在 vmSymbols.hpp 用宏定义的: 

    run

    run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。

    run方法源码示例

    分别测试start和run

     1 package org.fool.test.thread;  
     2   
     3 public class ThreadTest {  
     4     public static void main(String[] args) {  
     5         Thread thread = new Thread(new Runnable() {  
     6             @Override  
     7             public void run() {  
     8                 System.out.println(Thread.currentThread().getName() + " invoked...");  
     9             }  
    10         });  
    11         thread.start();  
    12         //thread.run();  
    13     }  
    14 }  

    先运行thread.start()

    Thread-0 invoked...  

    注释调thread.start()方法,运行thread.run()

    main invoked... 

    Summary

    start方法可启动多线程

    run方法只是thread的一个普通方法调用,还是在主线程里执行,是不会开启多线程的

  • 相关阅读:
    java基础(8)---接口和lambda
    asp.net ashx处理程序中switch case的替代方案总结
    C# 委托(delegate)、泛型委托和Lambda表达式
    js判断浏览器是否安装或启用了flash的方法总结
    ASP.NET登录验证码解决方案
    C#读取匿名对象的属性值的方法总结
    C#中char[]与string之间的转换;byte[]与string之间的转化
    【Sublime】Sublime 常用插件
    js ajax设置和获取自定义header信息的方法总结
    .Net 通过设置Access-Control-Allow-Origin来实现跨域访问
  • 原文地址:https://www.cnblogs.com/agilestyle/p/11421515.html
Copyright © 2011-2022 走看看