Java中通过Runnable与Thread创建线程的区别
Posted javartisan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中通过Runnable与Thread创建线程的区别相关的知识,希望对你有一定的参考价值。
1 、Java中的Thread与Runnable
1:在Java并发模型中,Thread是跟操作系统底层的线程一对一对应的,Thread对应一个真实的操作系统线程。
2:Runnable只是一个线程执行代码片段的接口标准之外,其余跟线程关系根本不是很大(可以理解:Runnable是一个线程的Task抽象)。Runnable可以理解为线程执行代码的一个单元(juc中Callable也是一个接口标准,可以结合线程池使用,使得线程执行代码,Callable跟Runnable的定义标准有差别:Callable中重写call方法,之外还可以有返回值以及允许跑出异常)。
为什么说Runnable是Thread执行代码的标准呢?
public
class Thread implements Runnable
private Runnable target;
/* Make sure registerNatives is the first thing <clinit> does. */
private static native void registerNatives();
static
registerNatives();
@Override
public void run()
//默认实现
if (target != null)
target.run();
//忽略代码
Thread实现了Runnable接口,当我们通过继承Thread创建线程时,需要重写run方法,将自己需要执行逻辑放到run中即可;这也就指定标准,用户如何实现线程执行的代码片段。(马士兵说过:一流公司卖标准,标准定义好之后你们按照标准随你们便玩;JDK定义标准,用户按照标准用户随便用)。这也正是创建线程的一种方式。
除此之外而另一种创建是实现Runnable接口,之后将Runnable通过构造器传到Thread中,之后线程启动调用Thread的默认run实现运行任务呢,默认run实现如上代码。
备注:还有一种线程运行代码片段的方法是线程池+Callable实现。
2、两种方式有什么区别?
(一)
1:继承的方式最好之处就是定制,私人定制。例如你去餐厅吃饭,每次都点套餐吃,日子久了你厌倦了,想换个吃法,此时你的吃法餐厅没有现成的套餐可以满足你,此时怎么办?那就是定制,跟老板沟通你的需求,进行私人订制。
class TimeCostThread extends Thread
public TimeCostThread(Runnable r)
super(r);
@Override
public void run()
System.out.println("start at = " + LocalDate.now());
super.run();
System.out.println("start at = " + LocalDate.now());
例如,业务需要对任何线程执行的任务都需要记录耗时,此时你可以在你的Task中进行记录耗时,但是假如你有千百个分散不同处时候修改Task很麻烦,此时你就可以自定一个线程满足你的需要。所以继承Thread方式更好的是满足定制需求。
除此之外,
2:创建时资源占,Thread里面有很多局部变量,而Runnable没有。:
3:继承Thread,会将业务代码耦合在Thread中,没有Runnable清晰。
(二)
实现Runnable方式创建线程更多是实现接口由于继承吧(单继承限制)。
1:至于网友说的:实现Runnable的方式代码片段可以共享给多个Thread执行的问题,其实继承Thread也是可以的,因此Thread是Runnable子类,例如:
public static void main(String[] args)
TimeCostThread t = new TimeCostThread(new Runnable()
@Override
public void run()
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
System.out.println("task finish!");
);
new Thread(t).start();
但是这种方式由于Thread成员变量以及安全等,比较耗费资源。
2:Thread有局部变量,创建Thread需要初始化局部变量。
3:Runnable比较干净,而且业务代码没有耦合在Thread中
(三)个人总结:
1:如果无需定制Thread默认行为,而仅仅是修改run方法行为的话,还是建议使用Runnable方式,使用实现接口方式更优雅。
2:如果有定制化需求的话,则进行继承Thread进行制定。
3:如果代码需要多次执行,推荐Runnable方式共享给执行线程,这种方式比较节约资源,并且启动速度快;Thread会差一些。
以上是关于Java中通过Runnable与Thread创建线程的区别的主要内容,如果未能解决你的问题,请参考以下文章
JAVA多线程继承Thread 与实现Runnable接口的相关疑问
java 创建线程的三种方法Callable,Runnable,Thread比较及用法