com.github.phantomthief.pool.KeyAffinityExecutorUtils#executor(java.lang.String, int)
在这里可以看到我们一直提到的“只有一个线程的线程池”,队列的长度也可以指定:
该方法返回的是一个 Supplier 接口,等下就要用到。
接下来,我们要找到 “3” 这个数字是体现在哪儿的呢?
就藏在构造函数的 build 方法里面,该方法最终会调用到这个方法来:
com.github.phantomthief.pool.impl.KeyAffinityImpl#KeyAffinityImpl
你到时候在这个地方打个断点,然后 Debug 看一眼,就非常明确了:
关于框起来的这部分的几个关键参数,我解释一下:
首先是 count 参数,就是我们定义的 3。那么 range(0,3),就是 0,1,2。
然后是 supplier,这玩意就是前面我们说的 executor 方法返回的 supplier 接口,可以看到里面封装的就是个线程池。
接着是里面有一个非常关键的操作 :map(ValueRef::new)。
这个操作里面的 ValueRef 对象,很关键:
com.github.phantomthief.pool.impl.KeyAffinityImpl.ValueRef
关键的地方就是这个对象里面的 concurrency 变量。
还记得最前面说的“挑选最闲置的执行器(线程池)”这句话吗?
怎么判断是否闲置?
靠的就是 concurrency 变量。
其对应的代码在这:
com.github.phantomthief.pool.impl.KeyAffinityImpl#select
能走到断点的地方,说明当前这个 key 是之前没有被映射过的,所以需要为其指定一个线程池。
而指定这个线程池的操作,就是循环这个 all 集合,集合里面装的就是 ValueRef 对象:
所以,comparingInt(ValueRef::concurrency) 方法就是在选当前所有的线程池,并发度最小的一个。
如果这个线程池从来没有用过或者目前没有任务在使用,那么并发度必然是 0 ,所有会被选出来。
如果所有线程池正在被使用,就会选 concurrency 这个值最低的线程池。
我这里只是给大家说一个大概的思路,如果要深入了解的话,自己去翻源码去。
如果你非常了解 lambdas 的用法的话,你会觉得写的真的很优雅,看起来很舒服。
如果你不了解 lambdas 的话...
那你还不赶紧去学?
另外我还发现了两个熟悉的东西。
朋友们,请看这是什么:
这难道不就是线程池参数的动态调整吗?
第二个是这样的:
RabbitMQ 里面的动态调整我也写过啊,也是强调过这三处地方:
增加 {@link #setCapacity(int)} 和 {@link #getCapacity()}
{@link #capacity} 判断边界从 == 改为 >=