一、这俩种方法在主线程(main)启动线程的区别:
1)继承了Thread类的Thread01(class Thread01 extends Thread {})
Thread01 thread01 = new Thread01();
thread01.start();
2)实现了Runnable接口的Thread01(class Thread01 implements Runnable {})
Thread thread = new Thread();
thread.start();
/*注 1
Thread 类的源码中存在属性:
/* What will be run. */
private Runnable target;
存在构造方法:
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
所以实例化Thread类时可以传入一个实现了 Runnable 接口的类的对象。
*/
/*注 2
为什么调用的都是 start() 方法,而不直接调用重写后的 run() 方法:
1、run() 方法只是个普通方法,直接使用thread对象调用负责创建线程的还是Thread的start方法,但新创建的线程的业务逻辑绑定到自定义类内run方法。
(具体来说,Thread 类中的 run() 方法是一个空方法,它在实现时并没有定义具体的线程执行逻辑。相反,它检查了 target 是否为 null,如果不为 null,则调用 target.run() 方法。)
这样任何类想创建线程实现自己业务逻辑都只需实现Runnable接口重写 run方法,再向Thread代理类传入对象就可实现。
深层思考: 为什么在主线程调用 start() 方法去启动线程的 run()
* 1、如果直接 自定类.run(); 那么就是由主线程 去直接找到 run(),那么在新创建的线程Thread.currentThread.getName() 打印出的线程名称就 变成主线程名 main。
* 2、且 主线程 mian 必须将 run()方法执行完成后,才会继续执行内部的其他代码。这样没有真正启动一个线程。
/* 源码解读
(1)public synchronized void start()
{
start0();
}
(2)//start0()是本地方法,由JVM调用,底层是c/c++实现
//真正实现多线程的效果,是start0(),而不是 run
private native void start0();
*/
说明:
1)Thread类(实现了接口Runnable)既可以被继承用于一个类的线程创建。
2)也可以作为 实现了Runnable接口的类 创建线程的代理,只要在 new Thread(object) 时,传入实现 Runnable的类的对象也能创建线程。
其他
1、从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口。
2、Java是单继承的,不继承thread是因为实际开发的需要,一般你自己的类都会继承一个父类,没法再继承thread类。
3、实现Runnable接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制,建议使用Runnable。
二、实际效用
实现Runnable的接口方式,是如何区别于继承Thread,使得多个线程共享一个资源的:
多线程——继承Thread 类和实现Runnable 接口的区别_继承thread类和实现runnable接口的区别-CSDN博客