实现Runnable接口
通过实现Runnable接口,新建一个Thread类传入Runnable接口,最终执行start方法
/**
* Runnable创建线程 将接口传入 执行Runnable run方法
*/
public class RunnableTest implements Runnable {
@Override
public void run() {
System.out.println("Runnable 创建thread线程");
}
public static void main(String[] args) {
new Thread(new RunnableTest()).start();
}
}
继承Thread类
通过继承Thread类,调用start方法
/**
* Thread 创建线程 将父类thread的run方法进行了重写
* */
public class ExtendsThreadTest extends Thread {
public static void main(String[] args) {
new ExtendsThreadTest().start();
}
@Override
public void run() {
System.out.println("Thread 创建线程");
}
}
两种方式作比较
在非不得已的情况下,我们最好是用实现Runnable接口的方法,为什么?请往下看
1.从代码架构上分析
在这里,我们要有一个概念,Thread类只是一个线程,是用来创建执行销毁线程的一系列线程生命周期,Runnable作为任务被传入到Thread类中,然后调用start方法执行该任务,在代码架构上说,线程和任务应该是解耦的,他们互不相干
2.线程复用
实现Runnable接口的任务以被多个线程复用(new Thread(Runnable)),而继承的方式需要每次新建一个实现类来执行任务
3.java不支持双继承
一旦通过继承的方式就无法多继承,如果你的类上要继承其他基类的需求就无法完成
正确启动线程 run方法和start方法
/**
* @Description: start方法和run方法做比较
*/
public class Test01 implements Runnable {
public static void main(String[] args) {
//构造一个实现Runnable接口的对象
Test01 runnable = new Test01();
//执行run方法
runnable.run();
//新建一个线程复用Runnabl接口 调用start方法
new Thread(runnable).start();
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
输出
结果显示,直接调用run方法是当前main线程去调用的,并不是真正的开启了一个新线程。
start方法只能被执行一次
/**
* @Description: start方法只能被执行一次
*/
public class Test02 implements Runnable{
public static void main(String[] args) {
Thread thread = new Thread(new Test02());
//执行两次start()
thread.start();
thread.start();
}
@Override
public void run() {
System.out.println("执行了run方法");
}
}
输出
我们可以清晰的看到,抛出了非法线程状态的异常,我们来看一下源码
start方法源码
/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
//初始化状态是0
private volatile int threadStatus = 0;
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 {
//调用了一个native方法 执行线程
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 */
}
}
}
run 方法源码
public void run() {
//target 是传入的Runnable接口
// 这里需要注意的是 继承Thread类的线程 会重新Thraed类的run方法
if (target != null) {
//target 不为空就执行
target.run();
}
}