创建线程的两种方式
- 编写一个类实现Runnable接口,并将此类的对象作为参数传入Thread类
package online.stringtek.javaconcurrency.createthreads;
/**
* 用Runnable方式创建线程
* */
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("使用实现Runnable接口方式创建线程");
}
}
public class RunnableStyle {
public static void main(String[] args) {
Thread thread=new Thread(new MyRunnable());
thread.start();
}
}
- 编写一个类继承Thread对象,并重写run方法
package online.stringtek.javaconcurrency.createthreads;
class MyThread extends Thread{
@Override
public void run() {
System.out.println("使用继承Thread类方式创建线程");
}
}
public class ThreadStyle {
public static void main(String[] args) {
MyThread thread=new MyThread();
thread.start();
}
}
两种创建方法的对比
通常情况下使用实现Runnable接口的方式来创建线程是更好的,不是在迫不得已的情况下,通常我们都应该选择这种方法来创建线程。这种创建线程的方法有一下几点好处。
- 从代码架构的角度来考虑,具体执行的任务应当与线程的各种状态代码,创建运行机制分离开来,也就是解耦。
- 继承了Thread类,由于Java的单继承导致它无法继承其他的类。
- Runnable配合线程池可以大大减少对象创建的损耗,如果是继承Thread类的方式的话就得创建新的对象麻烦,开销也相对较大。
本质区别
- 实现Runnable接口传入Thread,这个Thread会把Runnable的对象作为他的一个成员变量target,当调用run的时候会去调用target.run()
- 直接继承Thread的话,就是直接重写run方法
以下是Thread类run()的源码
/**
* If this thread was constructed using a separate
* <code>Runnable</code> run object, then that
* <code>Runnable</code> object's <code>run</code> method is called;
* otherwise, this method does nothing and returns.
* <p>
* Subclasses of <code>Thread</code> should override this method.
*
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
问题:如果同时使用两种方法创建线程会怎么样?
首先给出同时使用两种方法的代码
package online.stringtek.javaconcurrency.createthreads;
public class StupidStyle {
public static void main(String[] args) {
Thread thread=new Thread(()->{
System.out.println("实现Runnable");//这里使用Lambda等同于new Runnable{....}
}){
@Override
public void run() {
System.out.println("继承Thread");
}
};
thread.start();
}
}
很明显结果是继承Thread,因为正如上面讲的本质区别,继承Thread会重写整个run方法,所以当调用thread.run()的时候,根本就不会去管传入的Runnable而是直接执行重写的run方法。
补充
准确的来说,实现线程只有一种方式,那就是构造一个Thread类,但是实现线程执行单元可以有两种方式。除此之外,从表面上看线程池、定时器等工具类也可以创建线程,但是它们的本质都逃不出刚才所说的范围。