初学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()方法并不能达到此效果。