看到一个魔改线程池,面试素材加一! (6)

部分 signal() 信号触发改为 signalAll()

另外作者还提到了 RabbitMQ 的版本里面会有导致 NPE 的 BUG 的问题。

这个就没细研究了,有兴趣的可以去对比一下代码,就应该能知道问题出在哪里。

说说 Dubbo

为什么要说一下 Dubbo 呢?

因为我似乎在 Dubbo 里面也发现了 KeyAffinityExecutor 的踪迹。

为什么说是似乎呢?

因为最终没有被合并到代码库里面去。

看到一个魔改线程池,面试素材加一!

其对应的链接是这里:

https://github.com/apache/dubbo/pull/8975

这一次提交一共提交了这么多文件:

看到一个魔改线程池,面试素材加一!

里面是可以找到我们熟悉的东西:

看到一个魔改线程池,面试素材加一!

其实思路都是一样的,但是你会发现即使是思路一样,但是两个不同的人写出来的代码结构还是很不一样的。

Dubbo 这里把代码的层次分的更加明显一点,比如定义了一个抽象的 AbstractKeyAffinity 对象,然后在去实现了随机和最小并发两种方案。

在这些细节处上是有不同的。

但是这个代码的提供者最终没有用这些代码,而是拿出了一个替代方案:

看到一个魔改线程池,面试素材加一!

https://github.com/apache/dubbo/pull/8999

在这一次提交里面,他主要提交了这个类:

org.apache.dubbo.common.threadpool.serial.SerializingExecutor

这个类从名字上你就知道了,它强调的是串行化。

带大家看看它的测试用例,你就知道它是怎么用的了:

看到一个魔改线程池,面试素材加一!

首先是它的构造方法入参是另外一个线程池。

然后提交任务的时候用 SerializingExecutor 的 execute 方法进行提交。

在任务内部,干的事就是从 map 里面取出 val 对应的 key ,然后进行加 1 操作再放回去。

大家都知道上面的这个操作在多线程的情况是线程不安全的,最终加出来的结果一定是小于循环次数的。

但是,如果是单线程的情况下,那肯定是没问题的。

那么怎么把线程池映射为单线程呢?

SerializingExecutor 干得就是这事。

而且它的原理特别简单,核心代码就几行。

首先它自己搞了个队列:

看到一个魔改线程池,面试素材加一!

提交进来的任务都扔到队列里面去。

接下来再一个个的执行。

怎么保证一个个的执行呢?

方法有很多,它这里是搞了个 AtomicBoolean 对象来控制:

看到一个魔改线程池,面试素材加一!

这样就实现了把多线程任务搞成串行化的场景。

只是让我奇怪的是 SerializingExecutor 这个类目前在 Dubbo 里面并没有使用场景。

但是,如果你时候你就要实现这样奇怪的功能,比如别人给你一个线程池,但是到你的流程里面出入某种考虑,需要把任务串行化,这个时候肯定是不能动别人的线程池的,那么你可以想起 Dubbo 这里有一个现成的,比较优雅的、逼格较高的解决方案。

最后说一句

好了,看到了这里了, 转发、在看、点赞随便安排一个吧,要是你都安排上我也不介意。写文章很累的,需要一点正反馈。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwfzjd.html