Java多线程:Thread类中为什么调用start()方法而不是run()方法

初学Java,多方查找资料加上自己的一点见解。

进程与线程参考文章:https://www.cnblogs.com/qianqiannian/articles/7010909.html?tdsourcetag=s_pctim_aiomsg

多线程要执行的功能都应该在run()方法中定义。需要注意的是在正常情况下要使用一个类中的方法,那么是要产生这个类的一个实例化对象,然后去调用类中提供的方法,但是run()方法不能够被直接调用,因为操作系统的资源调度问题,要想启动多线程必须使用start()方法完成这里说的不是不能通过 对象.run(); 的调用操作,而是使用 对象.run(); 不能实现多线程。

如果是直接调用run(),则是顺序执行的,不是多线程

通过start()方法是多线程的,注意多线程每次运行的结果不一样,这是因为子线程启动的时间不确定

然后看一下JDK 1.9中对run()方法的解释

public void run();

If this thread was constructed using a separate Runnable run object, 
then that Runnable object's run method is called; 
otherwise, this method does nothing and returns.

如果这个线程是使用一个单独的Runnable运行对象构造的,
那么调用该Runnable对象的run方法;
否则,此方法不执行任何操作并返回。

就是说,你需要自己定义一个类继承Thread类并覆写run()方法,否则当你调用run方法时什么都不会做。

上面也说了,启动多线程必须使用start方法,那么再看一下start方法

public void start​()

Causes this thread to begin execution; 
the Java Virtual Machine calls the run method of this thread.

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

在start()中说的很清楚了,start()方法就相当于一个按钮,按下这个按钮后由JVM来调用你的run()方法。

看一下完整说明:

那么问题来了 为什么多线程的启动不直接run()方法,而必须使用Thread类中的start()方法呢?

先看start的源码

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. */
        group.add(this);

        boolean started = false;
        try {
            start0();    // 在start()方法中调用start0()
            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

start()方法里会抛出一个 “IllegalThreadStateException” 异常类对象,但整个程序并没有throws和 try..catch 处理,因为该异常一定是RuntimeException的子类,每一个线程类的对象只允许启动一次,如果重复启动则抛出此异常。

例如:

该代码会抛出异常

public class Main {

	public static void main(String[] args) {
//		new MyThread("线程A").start();
//		new MyThread("线程B").start();
//		new MyThread("线程C").start();
		
		MyThread mt = new MyThread("线程D");
		mt.start();
		mt.start();    // 重复启动线程
	}
}

执行结果:

再看这几行代码

try {
    start0();    // 在start()方法中调用start0()
    started = true;
}


private native void start0();    // 只定义方法名称没有实现,返回类型native

什么native:

在Java程序执行的过之程中考虑到对于不同层次的开发者的需求,所以其支持有本地的操作系统函数调用,而这项技术被称为JNI(Java Native Interface)技术,但是Java开发过程中并不推荐这样使用,利用这项技术可以使用一些操作系统提供的底层函数,进行一些特殊的处理,而在Thread提供的start0就表示需要将此方法依赖于不同的操作系统实现。

所以 为什么多线程的启动不直接run()方法,而必须使用Thread类中的start()方法呢?

原因就是Java以良好的跨平台可移植性著称,而在不同的操作系统之中他的资源调度算法是不同的,但操作系统会提供底层函数来进行资源调度。所以当我们在Java程序中调用start()方法时,然后start()方法会去调用start0(),而start0()只有定义没有实现,那么实现是由谁来做的呢?是JVM来做,JVM会根据用户系统类型实现相应的start0()方法,以此实现多线程。而直接调用run()方法并不能达到此效果。

发布了238 篇原创文章 · 获赞 104 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/hpu2022/article/details/103152114