创建线程的方式

前置说明

Thread类的作用:(创建线程、启动线程,中止线程、定义线程)概括来说就是:定义线程和操作线程,但线程要执行的任务Thread类自身并不定义,而是通过构造函数从外部传入且只接受Runnable函数式接口定义的任务

Runnable函数式接口的作用:定义线程要执行的任务,方法无返回值,不可以抛出异常,有异常需要自行捕获。

Callable<V>函数式接口的作用:和Runnable函数式接口类似,用来定义线程要执行的方法,可以有返回值,可以抛出异常,返回值类型由泛型指定;但和Runnable接口不同的是线程不接受Callable接口定义的任务,如果想线程能够执行Callable任务需要配合FutureTask一起使用。

FutureTask<V>类的作用:为线程提供可执行的任务,该类有两个构造函数,一个可以接受Runnable实例和一个泛型两个参数,另一个可以接受Callable实例参数(一般都是用这个);该类实现RunnableFuture<V>接口继承了Runnable, Future<V>这两个接口,所以FutureTask类可以说是Runnable, Future这两个接口的实现类(Future<V>接口的作用是让我们可以方便的操作Callable<V>接口的返回值),而由于Thread只接受Runnable的任务,所以Thread也可以接受FutureTask的任务,而FutureTask类中的任务实际内容又是调用构造函数入参中Runnable和Callable实例中定义的任务。也就是说FutureTask自身并不生产任务,他只是任务的搬运工。

前置总结:如果想创建一个有任务可执行的线程,就必须向Thread类的构造函数中传入一个Runnable的实现类,这个实现类可以是Runnable接口的直接实现类,也可以是间接实现类。

线程的四大创建方式

1、继承Thread类

由于Thread类实现了Runnable接口,因此我们只需要创建一个Thread类的子类并重写父类的run方法

然后使用Thread类中接受Runnable任务的构造函数创建一个线程实例,并将前面继承Thread类的子类作为入参传入,然后就可以使用Thread类的 start 方法启动一个有任务可以执行的线程。

2、实现Runnable接口

由于Thread类只接受Runnable接口定义的任务,所以想要创建一个有任务可以执行的线程,我们可以实现Runnable接口,然后将该Runnable实现类作为参数传入Thread类的构造函数来创建线程,最后使用Thread类的 start 方法启动一个有任务可以执行的线程。

3、实现Callable<V>接口

由于实现Callable<V>接口的任务不能直接作为Thread类的执行任务,所以我们可以通过结合FutureTask类,将Callable接口的实现类实例作为参数传入FutureTask类的对应构造函数,然后将构造的FutureTask类实例作为入参传入Thread类的构造函数来创建一个线程,最后使用Thread类的 start 方法启动一个有任务可以执行的线程。

4、使用线程池

我们可以使用 Executors 线程工具类 ExecutorService service = Executors.newFixedThreadPool(10);来创建一个有10个线程的线程池,线程池中的所有线程都处于无任务可执行的等待状态,所以我们可以向线程池中传入Runnable接口间接或直接实现类任务。 service.execute(new NumberThread());

也可以使用 下面的ThreadPoolExecutor类的构造函数来创建线程池

ThreadPoolExecutor(int corePoolSize,
                   int maximumPoolSize,
                   long keepAliveTime,
                   TimeUnit unit,
                   BlockingQueue<Runnable> workQueue)

corePoolSize 指的是核心线程数,

这些核心线程一直存在,是线程池的最小线程数,除非我们设置了 allowCoreThreadTimeOut 来允许核心线程超时回收,

maximumPoolSize 指的是最大线程数

当系统迎来大量请求需要大量线程来处理时,核心线程已经不足以来处理这么多请求,因此需要创建更多的线程,这个最大线程数就是就是系统线程池允许的线程峰值

keepAliveTime 存活时间

当线程池中的线程数大于核心线程数,且超出核心线程数的那部分线程中的空闲线程空闲多久会被回收释放

unit 存活时间的单位

workQueue 异步任务阻塞队列

当请求过大,最大线程数的线程还不足以及时处理,那些等待被处理的请求会被存放在异步任务阻塞队列中等待线程处理,我们可以使用 BlockingQueue 接口的实现类,例如:LinkedBlockingQueue阻塞队列,但我们不要使用其默认的初始化容量,而推荐自己根据系统的吞吐量设置一个合适的初始化容量,因为LinkedBlockingQueue 的默认初始化容量为Integer类型的最大值,该值过大容易导致内存爆满。

总结:在上面的四种线程创建方式中,推荐使用线程池的方式来创建线程,其优势如下:

1、降低系统资源的消耗,通过重复利用提前创建好的线程可以降低线程频繁的的创建和销毁。

2、提高系统的响应速度,由于线程池提前创建好了一批线程,所以当请求到来时就可以立马处理,而不需要等待线程创建。

3、方便管理线程, 线程池会根据当前系统特点对池内的线程进行优化处理 通过线程池我们可以动态的定义系统的线程大小,线程的存活时间等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值