Java理论二: 线程池的概念

参考:《并发艺术》相关章节
Java线程池实现原理及其在美团业务中的实践【推荐】 https://mp.weixin.qq.com/s/baYuX8aCwQ9PP6k7TDl2Ww
细说线程池—高级篇
细说线程池–中级篇
细说线程池—入门篇

1 线程池的概念和处理

1.1 线程池概念

1、线程池作用
线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,需要时候调用而不创建,池中线程执行调度由池管理器来处理。

//创建一个可重用固定线程数的线程池  
ExecutorService pool = Executors.newFixedThreadPool(2);  
//创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口  
Thread t1 = new MyThread();  
//将线程放入线程池中进行执行  
pool.execute(t1);   
//关闭线程池  
pool.shutdown();  

2、线程池分类:

  • 固定尺寸的线程池——newFixedThreadPool
    超过最大池线程数就排队,数量固定(无限制),一次性开销,没有超时限制不会回收,适合事件驱动的系统。

  • 单任务线程池——newSingleThreadExecutor
    只有一个核心线程,确保和统一任务都在一个线程中顺序执行(不需要处理同步)。

  • 可变尺寸连接池——newCachedThreadPool
    数量不定,只有非核心线程。

  • 延迟连接池——newScheduledThreadPool
    核心数量固定、非核心没有数量限制(闲置立即回收),用于定时/周期性任务。

  • 单任务延迟连接池——newSingleThreadScheduledExecutor
    自定义线程池

3、线程池的好处
1)重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。
2)能有效控制线程池的最大并发数,避免大量线程之间因互相争抢系统资源而导致的阻塞现象。
3)能够对线程进行简单的管理,并提供定时执行以及只想间隔循环执行等功能。

1.2 线程池的处理流程:[重要]

1、新任务进入线程池的处理过程:
在这里插入图片描述

当新提交一个任务时:
(1)如果poolSize<corePoolSize,新增加一个线程处理新的任务。
(2)如果poolSize=corePoolSize+阻塞队列未满,新任务会被放入阻塞队列等待,否则(3)。
(3)如果阻塞队列满了+ poolSize<maximumPoolSize,新增线程来处理任务。
(4)如果阻塞队列满了+ poolSize=maximumPoolSize,那么线程池已经达到极限,会根据饱和策略RejectedExecutionHandler拒绝新的任务。

【注】核心线程大小、最大线程池大小、当前线程池大小 关系:
corePoolSize:线程池的基本大小。
maximumPoolSize:线程池中允许的最大线程数。
注意还有一个largestPoolSize,记录了曾经出现的最大线程个数。因为setMaximumPoolSize()可以改变最大线程数。
poolSize:线程池中当前线程的数量。

2 线程池的使用及原理

2.1 线程池实现原理

在这里插入图片描述

workers :Worker工作线程集合set
workers是HashSet类型,它是一个Worker工作线程集合。而一个Worker对应一个线程。当Worker对应的线程池启动时,它会执行线程池中的任务;当执行完一个任务后,它会从线程池的阻塞队列中取出一个阻塞的任务来继续运行。
workers的作用:线程池通过它来实现了“允许多个线程同时运行”。

workQueue:任务队列
workQueue是BlockingQueue类型,它是一个阻塞队列。当线程池中的线程超过它的容量的时候,线程会进入阻塞队列进行阻塞等待。
workQueue的作用是:让线程池实现了阻塞功能。

2.2 线程池数据结构

在这里插入图片描述

1、mainLock :互斥锁,k实现了对线程池的互斥访问。

2、corePoolSize和maximumPoolSize
corePoolSize是“核心池大小”,maximumPoolSize是“最大池大小”。
核心大小与最大大小的作用:调整“线程池中实际运行的线程的数量”。
可以使用setCorePoolSize(int)和setMaximumPoolSize(int)进行动态更改。

3、poolSize:当前线程池的实际大小,即线程池中任务的数量。

4、allowCoreThreadTimeOut:是否允许线程在空闲状态时,仍然能够存活。

5、keepAliveTime :线程活动保持时间,表示被容忍的最大空闲时间。

6、threadFactory:创建线程的工厂。

7、handler:是“线程池拒绝策略”的句柄,也就是说“当某任务添加到线程池中,而线程池拒绝任务时,线程池会通过handler进行相应的处理”。

8、RejectedExecutionHandler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采用一种策略处理提交的新任务。
AbortPolicy(默认):直接抛出异常
CallerRunsPolicy:只有调用者所在线程来运行任务
DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务
DiscardPolicy:不处理,丢弃掉
自定义策略:可以实现RejectExecutionHandler接口自定义策略,如记录日志/持久化存储不能处理的任务

2.3 四种阻塞队列类型可选

1、ArrayBlockingQueue—基于数组结构的有界阻塞队列
按照FIFO原则对元素进行排序

2、LinkedBlockQueue—基于链表结构的阻塞队列-- Executors.newFixedThreadPool()
按照FIFO原则对元素进行排序
吞吐量大于ArrayBlockingQueue

3、SynchronousQueue–不存元素的阻塞队列—Executors.newCachedThreadPool
每个插入操作必须等到另一个线程调用移除操作,否则操作一直处于阻塞状态,
吞吐量大于LinkedBlockQueue

4、PrioriBlockingQueue—有优先级的无限阻塞队列

2.4 线程池中任务的添加

1、excute():提交不需要返回值的任务-------将任务添加到线程池中执行。

2、addWorker():将第一个任务添加到线程池,并启动任务。

3、submit()—用于提交有返回值的任务。------实际上也是通过调用execute()实现的
线程池会返回一个future类型的对象,通过这个future对象可以判断任务的是否执行成功,并且可以通过future的get()方法来获取返回值, get(timeout,TimeUnit)会阻塞当前线程直到任务完成。

2.5 线程池的关闭

1、shutdown方法:----阻止新任务,执行完剩余。

2、shutdownNow方法:----阻止新任务,强行清空正在运行的剩余任务。
做的比较绝,它先将线程池状态设置为STOP,然后拒绝所有提交的任务。最后中断左右正在运行中的worker,然后清空任务队列。

实现原理:都是遍历线程池中的工作线程Worker,然后逐个调用线程的interrrupt方法来中断线程,所以无法响应中断的任务可能永远无法中止。
https://blog.csdn.net/u013332124/article/details/79587436#4_shutdownshutdownNow_362

2.6 使用Callable–需要返回值的线程

可返回值的任务必须实现Callable接口;
无返回值的任务必须Runnable接口。

3 合理的配置线程池

重点:分析任务的特性(性质不同的任务用不同规模的线程池分开处理)
1、任务的性质
CPU密集型任务:应该配置尽可能小的线程,如N+1。
IO密集型任务:由于IO密集型任务线程并不是一直执行任务,则应该配置尽可能多的线程,如2*N
混合型任务:可以选择是否进行拆分,如果可以拆分成IO密集型和CPU型任务,分解后执行的吞吐量将高于串行执行的吞吐量,如果这两个任务执行时间差别不是很大,则没必要拆分。

2、任务的优先级
高、中、低使用优先级队列来处理。

3、任务的执行时间
优先级不同的任务可以交给不同规模的线程池来处理,或者使用优先级队列,让执行时间短的任务来执行。

4、任务的依赖
是否依赖其他系统资源,依赖数据库连接的任务,因为提交SQL后需要等待一段时间才能获取结果,等待的时间越长,CPU空闲的时间就越长,那么线程数应该设置得越大,这样可以更好的利用CPU。

4 线程池的监控

可以通过线程池提供的参数进行监控+扩展线程池自定义线程池
线程池属性:

  • taskCount:线程池需要执行的任务数量。
  • completedTaskCount:线程池在运行过程中已完成的任务数量。
  • largestPoolSize:线程池里曾经创建的最大线程数量,可以直到线程是否满过。
  • getPoolSize:线程池的线程数量(只增不减)。
  • getActiveCount:获取活动的线程数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值