线程池【Java】

来自智得网
跳转至: 导航、​ 搜索

简介

Java的线程池实现

线程池是一种池化的技术,其实现是长期固定的维护数量在一定范围之内的线程资源,当新任务到达的时候可以使用这些资源执行任务。

线程池主要作用如下:

线程复用,创建以及销毁线程是成本较高的操作,线程池将线程池化之后降低响应的资源消耗。

提高响应速度,在线程池还有剩余线程的情况下,任务可以立即获取到可执行的线程资源。

减少线程泄漏的风险,线程资源是系统稀缺资源,线程池对线程的统一管理减少了线程被大量创建从而导致的系统风险。

原理

线程池有三个核心的模块,分别是执行任务的工作线程,存放任务的存储,以及拒绝策略。

工作线程

工作线程是执行任务的载体,也是池化的最重要的资源,工作线程的数量决定了线程池响应的速度,但是过多的池化线程资源,会造成线程资源以及内存资源的浪费,影响整个系统的吞吐量。同时大量线程会带来线程切换的成本,也会影响性能。

Java线程池的工作线程数量一般和两个值相关,corePoolSize和maximumPoolSize。

corePoolSize指定了线程池中核心线程的数量,所谓核心线程是值当线程池中的工作线程数量小于该值的时候,可以立即创建新的线程资源。

maximumPoolSize指定了线程池中最大的线程数量,当阻塞队列已满的情况下新任务进来,会创建新的线程直到maximumPoolSize。

如果使用无界的阻塞队列,则线程数量永远不会达到maximumPoolSize(maximumPoolSize>corePoolSize的情况)

阻塞队列

当线程池的数量达到corePoolSize的情况下,如果有新的任务需要执行,会将这些任务放入阻塞队列暂存,当有新的线程释放之后,会消费阻塞队列的数据。

阻塞队列基于AQS实现。

常见的阻塞队列有:

ArrayBlockingQueue,数组实现的阻塞队列。

LinkedBlockingQueue,链表实现的阻塞队列。

SynchronousQueue,SynchronousQueue只做为中转队列,不会有大于1的元素,任务进入SynchronousQueue,必须有线程将其消费。

拒绝策略

maximumPoolSize指定了线程池中最大的线程数量,当线程池已经到达最大数量并且队列也已经满的情况下,线程池会执行丢弃策略。

拒绝策略
AbortPolicy 丢弃任务,同时抛出异常。
DiscardPolicy 静默丢弃任务,使用该策略出现拒绝时容易被忽略。
DiscardOldestPolicy 静默丢弃任务,但是会按照时间序从最早进入队列的任务进行抛弃。
CallerRunsPolicy 由调用线程池的业务线程来执行。

应用

Java的线程池类结构图

线程池接口是ExecutorService,ExecutorService继承自Executor,Executor是对执行线程等操作的封装。

Executors是线程池的工具类,可以创建各种类型的线程池,常用的线程池有以下几类:

  • CachedThreadPool

创建线程池时会复用当前系统中已经存在的线程。

  • FixedThreadPool

固定大小的线程池,可以避免线程池进行频发扩缩容而影响效率。

  • SingleThreadExecutor

单线程的执行工具。