有多少种实现多线程的方式?
一、 从不同的角度看,会有不同的答案。
网络上查到的,答案不一,他们的回答不能算错。
下面我们正式进入 我对有多少种实现多线程的方式的理解吧
首先我们看一下oracle的java 有多少种实现多线程的方式:
我们从官方文档中可以看出,创建Java线程的方式有两种,分别是继承Thread类和实现Runnable接口创建线程
一、继承Thread类和实现Runnable接口创建线程
1.1 代码demo
我把demo的代码贴出来,一看就能懂啦!
/**
* 描述: 用Thread方式实现线程
*/
public class ThreadStyle extends Thread{
public static void main(String[] args) {
new ThreadStyle().run();
}
@Override
public void run() {
System.out.println("用Thread类实现线程");
}
}
//描述: 用Runnable方式创建线程
public class RunableStyle implements Runnable{
public static void main(String[] args) {
Thread thread = new Thread(new RunableStyle());
thread.start();
}
@Override
public void run() {
System.out.println("用Runnable方式实现线程");
}
}
1.2 两种方式的区别
方法一和方法二,也就是“继承Thread类然后重写run()”和“实现Runnable接口并传入
Thread类”在实现多线程的本质上,并没有区别,都是最终调用了start()方法来新建
线程。这两个方法的最主要区别在于run()方法的内容来源:
方法一:最终调用target.run();
方法二:run()整个都被重写
我们再看源码,加深理解
综上,准确来说,创建线程只有一种方式,就是构造Thread类,而实现run方法的执行单元有两种方式:
(1)继承Thread类覆盖run方法
(2)实现Runnable接口,并把实例化对象传给Thread
1.3 两种方式哪个更好?
实现 Runnable!接口 更好
(1)从代码架构角度:Runnable对象可以实现解耦,实现Runnable接口的run方法是具体的执行任务,并且现Runnable接口的类也不负责创建线程等工作。
(2)从新建线程的损耗:使用继承 Thread 的方式的话,那么每次想新建一个任务,只能新建一个独立的线程,而这样做的损耗会比较大,如果使用实现Runnable接口和线程池,就可以大大减小这样的损耗
(3)从扩展性角度:继承 Thread 类以后,由于 Java 语言不支持双继承,这样就无法再继承其他的类,限制了可扩展性
1.4 如果同时使用两种方式呢?会发生什么?
我们可以通过下图,清晰的看到,使用两种方式的结果是,只使用了继承Thread的方式,因为只要有继承Thread就会覆盖掉Thread的run方法(那三行代码),就不能调用到target对象的run方法。
二、通过线程池创建线程demo和源码解读
2.1 demo案例截图
2.2 源码分析
我debug源码发现,最终是通过实现Runnable接口的方式 实现的。 严格来说线程池是实现Runnable接口的方式创建线程的一个包装,不能算是方式
三、其他“创建线程的方式”(不能算严格意义上的方式)
计时器:也是对实现Runnable接口的方式创建线程的一个包装
匿名内部类和Lambda表达式:是快捷实现Runnable接口的方式创建线程
不管怎么创建,最本质的方式只有一种:构建Thread类;实现run方法的执行单元有两种途径
版权声明:
作者:十下
链接:https://blog.edkso.cn/?p=902
来源:十下博客
文章版权归作者所有,未经允许请勿转载。