一、实现多线程的方法到底有几种?
Oracle的官方文档中,实现多线程的方法有两种:
- 实现Runnable接口
- 继承Thread类
官方文档地址: https://docs.oracle.com/javase/8/docs/api/
二、简单使用两种方法实现多线程
1.实现Runnable接口
/**
* 实现多线程的方式1:实现Runnable接口
*/
public class RunnableTest implements Runnable{
public static void main(String[] args) {
Thread thread = new Thread(new RunnableTest());
thread.start();
}
// 实现Runnable接口的run()方法
@Override
public void run() {
System.out.println("Runnable实现多线程");
}
}
2.继承Thread
/**
* 实现多线程的方式2:继承Thread
*/
public class ThreadTest extends Thread{
public static void main(String[] args) {
new ThreadTest().start();
}
// 重写Thread类的run()方法
@Override
public void run() {
System.out.println("Thread实现多线程");
}
}
三、两种方法的对比
(1)通过实现Runnable接口来实现多线程这种方法更好
- 具体的线程任务内容应该与Thread解耦
- 使用继承Thread来实现多线程,当需要创建其他线程任务时,就需要创建一个新的Thread,这种损耗是比较大的。使用Runnable可以使用线程池来节约资源。
- java单继承的特性使得继承了Thread的类无法继承其他的类,限制了可拓展性。
(2)两种方法的本质对比
- 方法1: new Thread(runnable)是传入Runnable,调用了runnable.run()方法
- 方法2: Thread类的run()方法被重写,直接调用了子类的run方法
其中target就是new Thread()时传入的Runnable对象。
四、同时使用两种方法
创建Thread对象时传入Runnable,并且重写Thread的run()方法
/**
* 同时使用两种方法
*/
public class BothTest {
public static void main(String[] args) {
new Thread(new BothRunnable()){
@Override
public void run() {
System.out.println("我是Thread");
}
}.start();
}
}
class BothRunnable implements Runnable{
@Override
public void run() {
System.out.println("我是Runnable");
}
}
虽然在创建Thread对象时传入了Runnable,也就是Thread源码中的target存在,但是因为重写了Thread类的run()方法,原来的target.run()语句没有了,所以并不会执行传入runnable的run()方法。
五、实现多线程的方法最准确的描述
- 实现多线程的方法有两类
- 准确的讲,创建线程只有一种方式,就是构造Thread类,而实现线程执行单元有两种方式:一是实现Runnable接口的run方法,并把Runnable实例传给Thread;二是重写Thread类的run方法。
六、其他的不准确的说法
线程池、定时器等也能创建线程,但是他们的底层都是基于 实现Runnable接口 或继承Thread类 来实现的。