标签:两种 接收 core 利用 size unit 努力 参数 repo
线程池使用了一种池化技术,和很多其他池化技术一样,都是为了更高效的利用资源,例如链接池,内存池等等
线程池一共有五种状态,运行状态,待关闭状态,停止状态,整理状态,终止状态,一个线程池的核心参数有很多,每个参数都有着特殊的作用,各个参数聚合在一起 后将完成整个线程池的完整工作,每一个工作线程中都维持着一个Thread,线程池的重点之一就是控制线程资源合理高效的使用,所以必须控制工作线程的个数,所以要保存当前线程中的工作线程个数。
线程池设计了两个变量来协作,分别是核心线程数和最大线程数,核心线程数是用来表示线程池中的核心线程的数量,也可以称之为可闲置的线程数量,最大线程数是用来表示线程池中最多能够创建的线程数量,创建线程就交给线程工厂ThreadFactory来完成,当线程池接收到一个任务时,如果工作线程数没有达到corePoolSize,那么就会新建一个线程,并绑定任务,直到工作线程的数量达到corePoolSize前都不会重用之前的线程,当工作线程数达到corePoolSize了,又接到新任务的时候,会将任务存放在一个阻塞队列中,等待线程去执行,核心线程中很可能已经有线程执行完自己的任务了,或者有其他线程马上就能处理完当前的任务,并且接下来就能投入到新的任务中去,所以阻塞队列是一种缓冲的机制,给核心线程一个机会让他们充分发挥自己的能力。另外一个值得考虑的原因是,创建线程毕竟是比较昂贵的,不可能一有任务要执行就去创建一个新的进程,所以我们需要为线程池配备一个阻塞队列,用来临时缓存任务,这些任务将等待工作线程执行。
当工作线程数达到 corePoolSize 时,线程池会将新接收到的任务存放在阻塞队列中,而阻塞队列又两种情况:一种是有界的队列,一种是无界的队列。如果是无界队列,那么当核心线程都在忙的时候,所有新提交的任务都会被存放在该无界队列中,这是最大线程数将变得没有意义,因为阻塞队列不会存在被装满的情况。
如果是有界队列,那么当阻塞队列中装满了等待执行的任务,这时再有新任务提交时,线程池就需要创建新的“临时”线程来处理,相当于增派人手来处理任务。
但是创建的“临时”线程是有存活时间的,不可能让他们一直都存活着,当阻塞队列中的任务被执行完毕,并且又没有那么多新任务被提交时,“临时”线程就需要被回收销毁,在被回收销毁之前等待的这段时间,就是非核心线程的存活时间,也就是 keepAliveTime 属性。
其实核心线程跟创建的先后没有关系,而是跟工作线程的个数有关,如果当前工作线程的个数大于核心线程数,那么所有的线程都可能是“非核心线程”,都有被回收的可能。
一个线程执行完了一个任务后,会去阻塞队列里面取新的任务,在取到任务之前它就是一个闲置的线程。
取任务的方法有两种,一种是通过take()方法一直阻塞直到取出任务,另一种是通过poll(keepAliveTime,timeUnit)方法在一定时间内取出任务或者超时,如果超时这个线程就会被回收,请注意核心线程一般不会被回收。每个线程想要保住自己“核心线程”的身份,必须充分努力,尽可能快的获取到任务去执行,这样才能逃避被回收的命运。
标签:两种 接收 core 利用 size unit 努力 参数 repo
原文地址:https://www.cnblogs.com/ggrm/p/11048649.html