开启线程为什么是执行start()方法而不直接执行run()方法

先看一段代码
public class Battles {
    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run(){
                pong();
            }
        };
        t.run();//重点在这,此处执行的是run()方法
        System.out.println(Thread.currentThread().getName());
        System.out.println("ping");
    }
    private static void pong() {
        System.out.println(Thread.currentThread().getName());
        System.out.println("pong");
    }
}

大家可以试想一下输出是什么,在以往创建线程执行start()方法来看,新建的线程似乎比main线程要慢一点,“ping”和“pong”的输出可能并没有固定的顺序,而代码并不是执行的start()方法而是直接执行run()方法,到底有什么不一样呢,start()方法不依旧会执行run()方法吗?

先看结果:

main
pong
main
ping

发现了奇怪的一点,重写的run方法在输出线程名字的时候居然也是main,这两个线程都是用的同一个main线程,难道new Thread并没有帮我创建新线程吗?

带着这个疑问,深究一下start()方法和run()方法的区别----------直接上源码:

首先看run()方法

    @Override
    public void run() {
        if (target != null) {
            target.run();    //没有多余的操作,直接调用了重写的run()方法,并没有创建线程的操作
        }
    }

锁定start()方法

public synchronized void start() {       //首先表明了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();
            
        group.add(this);

        boolean started = false;
        try {
            start0();   //核心的地方就是调用了satrt0()方法
            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 */
            }
        }
    }


	private native void start0();    //该方法并没有方法体,却有一个native的关键字修饰

先讲讲native关键字,native method就是Java调用非Java代码的接口,就是说native method 的方法实现由其他语言实现的,比如C语言等

/* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();  //在这个静态代码块中就使用了registerNatives将本地方法加载进来供给native method使用
    }

start0()方法会调用本地文件中的方法---------------还有诸多常见方法,如stop0,isAlive,yield,sleep等

static JNINativeMethod methods[] = {
    {"start0",           "()V",        (void *)&JVM_StartThread}, // 可以看出调用了JVM_StartThread
    {"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},
    {"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},
    {"suspend0",         "()V",        (void *)&JVM_SuspendThread},
    {"resume0",          "()V",        (void *)&JVM_ResumeThread},
    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
    {"yield",            "()V",        (void *)&JVM_Yield},
    {"sleep",            "(J)V",       (void *)&JVM_Sleep},
    {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},
    {"countStackFrames", "()I",        (void *)&JVM_CountStackFrames},
    {"interrupt0",       "()V",        (void *)&JVM_Interrupt},
    {"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},
    {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},
    {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},
    {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
    {"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};
#undef THD
#undef OBJ
#undef STE
#undef STR
JNIEXPORT void JNICALL
Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}

JVM_StartThread方法会创建一个本地线程,最终会去调用run方法

总的来说:Java的里面创建线程之后必须要调用启动方法才能真正的创建一个线程,该方法会调用虚拟机启动一个本地线程,本地线程的创建会调用当前系统创建线程的方法进行创建,并且线程被执行的时候会回调跑方法进行业务逻辑的处理

总结:开启线程为什么是执行start方法而不是执行run方法:直接调用run方法该线程并不会创建出来,而是直接使用主线程去执行重写的run逻辑,只有调用start方法才会创建一个新的本地进程,通过本地进程去执行重写的run逻辑
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值