浅谈如何理解线程池的概念

那么线程池是如何把线程统一分配调度与监控的呢?



【画图太累了,我就用的网图,图片来源视频:https://www.bilibili.com/video/av88030891


【画图太累了,我就用的网图,图片来源:https://blog.csdn.net/lchq1995/article/details/85230399


我们在NEW一个最基本的线程池的时候,会传入这么一下几个参数:
corePoolSize:线程池核心线程数量
maximumPoolSize:线程池最大线程数两
keepAliveTime:空闲线程存活时间

  • corePoolSize顾名思义就是最大核心线程数量,是线程池可以同时执行的线程数量。
  • maximumPoolSize,既然有corePoolSize,那么如果corePoolSize满了怎么办呢?这时候就会用到一个队列,叫阻塞队列Block Queue
    什么是BlockQueue?它有什么特点?
    既然是Queue,那么久满足队列模型的(FIFO)原则,一端放入,另一端取出。(First In First Out)
    阻塞队列有一个特点就是:在任意时刻,不管并发量有多高,永远只有一个线程能进行队列的如对或出队,所以BlockQueue是一个线程安全的队列。
    并且如果队列满了,只能进行出队操作,所有入队操作必须等待,也就是阻塞。
    如果队列为空,那么就只能进行入队操作,所有出队操作必须等待,也就是阻塞。
    一旦线程池的线程量满了,那么新被execute进来的线程,就会被存储进BlockQueue,BlockQueue的大小就是maximumPoolSize - corePoolSize的大小。

线程池和五种状态:

  • Running:能接受新的execute以及处理已添加的任务
  • Shutdown:不接收任何新的execute,可以处理已添加的任务
  • Stop:不接受任何新的execute,不处理已添加的任务
  • Tidying:所有任务已经终止,ctl记录的任务数量为0.
  • Termiated:线程池彻底终止,则线程池转换为Terminated状态。


那么这么多线程池状态和这么多线程的信息,是如何保存的呢?
这里线程池内部用到了一个32字节的Integer类型来记录线程池的状态和线程数量信息。



这个Integer类型的高3未二进制用来表示线程池的状态,后29为用来表示线程的数量。
线程池定义了这么几个数字作为线程的状态

RUNNING = -1
SHUTDOWN = 0
STOP = 1
TIDYING = 2
TERMINATED = 3

并且所有数字都想做移位29位。
《《 COUNT_BITS(COUNT_BITS=29)

最终会得到高三位为:
RUNNING = 111
SHUTDOWN = 000
STOP = 001
TIDYING = 010
TERMINATED = 011


他是怎么得到的呢?

我们来回顾一下基础

拿-1来举个例子
众所周知,
1在32位Integer的类型中二进制为:
0000 0000 0000 0000 0000 0000 0000 0001
那么-1就应该去1的反位并且再加上一个符号位1000
则,-1就应该为:
1000 1111 1111 1111 1111 1111 1111 1111
那么-1向左移位29位,低位补0,那么则
-1 《《 29 等于
1110 0000 0000 0000 0000 0000 0000 0000
所以高三位为111


所以这就是RUNNING的高三为为111的由来
后面的29位用于存储线程的数量。


这种应用基本数据高效存储的思想可以用于存储一些记录,有点就是不用去多个变量的读取,提升速度。


具体线程池的实现可以百度搜索JAVA线程池的实现,在这里只是浅谈一下线程池的好处以及浅层原理。

(本文完)

页面: 1 2

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Captcha Code