Java中的线程池设计思想

为什么要使用线程池

首先线程的创建和销毁需要调用操作系统内核的API,然后操作系统为其分配一系列资源,整个成本很高,也就导致线程是一个重量级对象。其次如果并发线程数量很多,并且每个线程执行一个很短的任务就结束了,这样频繁创建线程不仅会消耗系统资源,还会降低系统的稳定性。

为了避免资源的过度消耗,最好的办法就是用池化技术对线程进行复用,线程执行完一个任务并不需要销毁,而是让他继续执行其他任务。这样当任务到达时,任务可以不需要等到线程创建就能立即执行。

使用线程池对资源进行统一的分配、调度和监控,不仅可以减少频繁申请/销毁带来的额外消耗;同时可以避免因为对资源无线申请,而导致系统资源耗尽的风险;

线程池工作原理

线程池的实质就是实现线程复用,当我们使用JDK自带的线程池的时候,首先需要设置线程工作线程的数量(corePoolSize),当有任务产生首先创建工作线程来处理。

当任务提交的数量大于工作线程处理能力的时候,就会将任务暂存与我们预先设置的阻塞队列(workQueue)等待工作线程处理。假设无法将任务再加入BlockingQueue(队列已满),则创建新线程来处理,直到大于最大线程数(maximumPool)任务将会被拒绝,触发拒绝策略。

拒绝策略:
AbortPolicy:直接抛出异常(默认)
CallerRunsPolicy:谁提交的任务谁执行
DiscardOldestPolicy:丢弃队列最近的一个任务,并执行当前任务
DiscardPolicy:直接丢掉

线程池的弊端

我们再使用线程池的时候,通常来说使用的默认ThreadFactory。默认的Factory会使得我们线程的name无法见名知意,也会给后续排查OOM异常时候带来一些阻碍。所以一般情况下建议使用线程池的时候,实现ThreadFactory方法,设置一个和业务相关的线程名字。

猜你喜欢

转载自blog.csdn.net/qq_25448409/article/details/108480979