多线程并发编程之线程池应用及实现原理剖析

  1. 为什么要用线程池
  2. 线程池原理
  3. 线程池API

1 为什么要用线程池

  1. 线程在jvm中是一个对象,更是操作系统的资源,线程创建或销毁都伴随开销,如果创建时间+销毁时间>执行时间,就会不合理
  2. 对象是占用堆空间,操作系统线程占用系统资源,根据java虚拟机规范,一个线程默认允许占用的最大栈空间为1M,而栈空间是从系统内存分配的,如果开辟的线程太多,将会消耗大量内存
  3. 操作系统需要频繁切换线程上下文,会影响性能

线程不是越多越好,线程池的推出,就是为了方便控制线程数量,合理利用资源,提高资源利用率

2 线程池原理

  1. 概念
  2. 任务execute过程

2.1 概念

任务队列:用于存放没有处理的任务,提供缓存机制和拒绝策略。
工作线程:线程池中的线程,在没有任务执行时处于等待状态,可以循环执行任务。
线程池管理器:用于创建并管理线程池,包括创建线程池、销毁线程池和添加新任务。
任务接口:每个任务都必须实现的接口,以供工作线程调度执行,主要规定了任务的入口、任务执行后的收尾工作及任务的执行状态。

2.2 任务execute过程

  1. 过来一个新任务,如果没有达到核心线程数,则新建线程执行该新任务;
  2. 否则放入工作队列,若队列已满,则判断是否达到最大线程数;
  3. 若未达到最大线程数,则新建线程,否则执行拒绝策略;
  4. 若线程数超过最大线程数,线程空闲时会将线程终止;
  5. 若线程数未超过最大线程数,但设置了线程存活时间,则超过时间线程也会被终止
执行
达到核心线程数量
工作队列已满
达到最大线程数量
新建线程
丢到队列
新建线程
执行拒绝策略

3 线程池API

  1. 接口定义和实现类
  2. 方法定义
  3. Executors工具类

3.1 接口定义和实现类

类型名称描述
接口Executor最上层的接口,定义了执行任务的execute方法
接口ExecutorService继承了Executor接口,拓展了Callable、Future、关闭方法
接口ScheduledExecutorService继承了ExecutorService接口,拓展了定时任务相关的方法
实现类ThreadPoolExecutor基础、标准的线程池实现
实现类ScheduledThreadPoolExecutor拓展了定时任务相关的方法

3.2 方法定义

//---ExecutorService---
//监测线程池是否已经关闭,直到所有任务完成或发生超时或当前线程被中断
awaitTermination(long timeout, TimeUnit unit)

//执行给定的任务集合,执行完毕后,返回结果
invokeAll(Collection<? extends Callable<T>> tasks)

//执行给定的任务集合,任意执行一个成功则返回结果,其它任务终止
invokeAny(Collection<? extends Callable<T>> tasks)

//如果线程池已关闭,则返回true
isShutdown()

//如果关闭后所有任务都已完成,则返回true
isTerminated()

//优雅关闭线程池,之前提交的任务将被执行,但不会接受新任务
shutdown()

//尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行任务列表
shutdownNow()

//提交一个用于执行的Callable任务,并返回一个Future,用于获取Callable执行结果
submit(Callable<T> task)
//---ScheduledExecutorService---
schedule(Callable<V> callable, long delay, TimeUnit unit)
schedule(Runnable command, long delay, TimeUnit unit)
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)

以上方法会创建并执行一个周期性任务,过了初始延迟时间,第一次被执行,若一次任务执行时间超过周期时间,scheduleAtFixedRate会在任务执行结束后,立刻执行,而scheduleWithFixedDelay会在结束的时间基础上,计算执行延时。

3.3 Executors工具类

newFixedThreadPool(int nThreads)创建一个固定大小、无界任务队列的线程池(核心线程数=最大线程数)

newCachedThreadPool()创建一个大小无界的缓存线程池,工作队列为同步队列,线程空闲超过60s将被销毁释放(核心线程数为0,最大线程数为Integer.MAX_VALUE),线程数随任务数发生变化,适用于执行耗时较小的异步任务

newSingleThreadExecutor()创建只有一个线程、无界任务队列的线程池,适用于确保任务按加入顺序依次执行的场景,无需担心线程执行异常任务中止。

newScheduledThreadPool(int corePoolSize)能定时执行任务的线程池(核心线程数由参数决定,最大线程数为Integer.MAX_VALUE)

参考文章

网易云课堂《Java高级开发工程师》

结语

本人所有博客仅用于学习记录,不做任何商业用途,如涉及侵权,还请联系删除,感谢阅读,欢迎留言,一起进步~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值