面试高频问题:请问你知道创建线程有多少种方式吗?

本文介绍了Java中创建线程的五种方法:继承Thread并重写run方法,实现Runnable接口,实现Callable接口(配合FutureTask),使用线程池(包括固定、单线程、缓存和定时)以及自定义线程池。重点讲解了Callable接口和FutureTask在创建有返回值线程中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

①创建一个类继承Thread,然后重写run方法,(注意:void没有返回值

运行结果:

②实现Runnable接口,然后重写run方法,(注意:void没有返回值

运行结果:

这里我要多插几句话,一般我们都会使用java8提供的lamda表达式去使用Runnable接口的方式去创建线程,我先把代码写下来,然后我会在另一篇博客内容写为什么Runnable接口就可以这么写,以及什么情况下可以这样写。

运行结果:

③实现Callable接口,然后重写call方法,(注意:T泛型,有返回值

运行结果:

结果也标明,确实开始时间是2023-11-17 03:56:20,结束时间是2023-11-17 03:56:30

证明确实是10s之后才打印,所以得出结论:FutureTask实现类的get()方法(严谨来说是Future接口的get(),因为FutureTask implements Future接口)是阻塞的。

④通过Executors.newXXXThreadPool();

总共有四种线程池

-FixedThreadPool 一池固定线程n'数量

-SingleThreadExecutor 一池单线程

-CachedThreadPool 一池不固定线程数量

-ScheduledThreadPool 定时

这几个线程池我也会在另一篇博客上面详说,这里就先知道一下,混个眼熟。

⑤自定义线程池,new ThreadPoolExecutor(...参数),然后将任务提交调用.submit()或者.execute()

这里ThreadPoolExecutor的有参构造器总共有3个,如下:

这里是6个参数,缺少了RejectedExecutionHandler参数,但是该构造器最终还是会调用7个参数的构造器,只是把RejectedExecutionHandler传了默认的handler。

这里也是6个参数缺少了ThreadFactory参数,但是该构造器最终还是会调用7个参数的构造器,只是把ThreadFactory传了默认的defaultFactory。

最后一个就是7个参数的了。

那么这些参数到底代表什么含义呢?在另外一篇博客,我也会详说的。

这时候我们选择5个参数的自定义线程池。

运行结果:



所以最终创建线程的几种方式总共就这五种,现在我要说一下第三种实现Callable接口刚刚留下的问题了。为什么必须得请出FutureTask呢?

首先我们看一下Thread的构造器:我们可以通过在IDEA中使用快捷键CRTL+SHIFT+N搜索,输入Thread,我们会发现,看了一圈下来,Thread的构造器都是接收的Runnable接口对象,没有能直接接收Callable接口对象的。所以这时候我们就不能直接传入Callable接口对象了。那么我们还是从Runnable接口对象入手,看看Callable接口和Runnable接口是否存在父子继承关系,如果是Callable接口继承Runnable接口的话,那么我们也可以直接传入Callable接口对象。但是很遗憾,Callable和Runnable接口并不是这种关系,所以我们还是只能从Runnable的子接口入手,我们发现Runnable接口有一个子接口叫做Future接口,那么我们就可以直接往Thread(Runnable runnable)传入Future接口对象,而Future接口的实现类有现成的了,叫做FutureTask<T>,那么我们是不是可以直接这样子:

FutureTask futureTask = new FutureTask();

然后将future对象放到Thread(Runnable runnable)参数中。但是即使这样和Callable接口还是没产生关联啊,我们再看一下,这个FutureTask,它的构造器有一个可以接收Callable接口对象的。诺:

看到没有,所以我们是不是可以直接这样。

FutureTask futureTask = new FutureTask(Callable接口对象) ;

new Thread(futureTask).start() ;

所以我们这就是为什么需要请出FutureTask的原因了。

总结:

创建线程的方式一共有5种:

①创建一个类继承Thread,然后重写run方法,(注意:void没有返回值

②创建一个类实现Runnable接口,然后重写run方法,(注意:void没有返回值

③实现Callable接口,然后重写call方法,(注意:T泛型,有返回值

④通过Executors.newXXXThreadPool();

⑤自定义线程池,new ThreadPoolExecutor(...参数),然后将任务提交调用.submit()或者.execute()

最后:如果觉得我写的不错的话,麻烦给个赞赞,谢谢啦。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值