在java中有很多方式创建线程,比较被广泛接收的是两种方式的说法:
package com.jswdwsx;
public class ThreadStudy {
public static void main(String[] args) {
Thread thread1 = new Thread(new MyTask());
thread1.start();
Thread thread2 = new MyThread();
thread2.start();
}
}
class MyTask implements Runnable {
@Override
public void run() {
System.out.println("方式一 实现Runnable接口!");
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println("方式二 继承Thread类!");
}
}
- 方式一:实现Runnable接口,将该实现类的对象作为参数,传递给Thread构造方法,构造Thread对象
- 方式二:继承Thread类,重写run方法,构造这个Thread子类的对象
可以看到本质上都是构造一个Thread类,我们不妨回到问题:如何创建一个线程?
这个问题我们可以看得更深入一点:
这里如果理解为创建一个操作系统层面执行的线程,那么调用Thread类对象的start方法就可以创建一个线程。
如果是理解为java层面创建一个线程,那么可以看到我们上面的两种方式都是构造一个Thread对象(子类也是一个Thread)。
至于我们常常说到的两种方式,其实是两种实现线程运行内容的方式。
通过代码可以发现,实现Runnable接口和继承Thread类,都是为了override(实现/重写) run方法。
所以说,创建线程只有一种方式,就是构造Thread类。
至于其他方式
- 线程池
本质是用线程工厂创建线程,线程工厂还是使用new Thread(参数省略)方法来创建 - 有返回值的 Callable 创建线程
和实现Runnable接口一样,这只是实现线程运行内容的方式。Callable如何被执行,请看这篇文章 - 定时器 Timer
Timer类中有一个TimerThread成员变量,TimerThread依然继承自Thread - 匿名类和lambda表达式
都是实现Runnable接口的不同写法而已