线程基础:多任务处理——Fork/Join框架(解决排序问题)
来源:互联网 发布:安广网络客服电话 编辑:程序博客网 时间:2024/06/06 02:28
3. 使用Fork/Join解决实际问题
之前文章讲解Fork/Join框架的基本使用时,所举的的例子是使用Fork/Join框架完成1-1000的整数累加。这个示例如果只是演示Fork/Join框架的使用,那还行,但这种例子和实际工作中所面对的问题还有一定差距。本篇文章我们使用Fork/Join框架解决一个实际问题,就是高效排序的问题。
3-1. 使用归并算法解决排序问题
排序问题是我们工作中的常见问题。目前也有很多现成算法是为了解决这个问题而被发明的,例如多种插值排序算法、多种交换排序算法。而并归排序算法是目前所有排序算法中,平均时间复杂度较好(O(nlgn)),算法稳定性较好的一种排序算法。它的核心算法思路将大的问题分解成多个小问题,并将结果进行合并。
整个算法的拆分阶段,是将未排序的数字集合,从一个较大集合递归拆分成若干较小的集合,这些较小的集合要么包含最多两个元素,要么就认为不够小需要继续进行拆分。
那么对于一个集合中元素的排序问题就变成了两个问题:1、较小集合中最多两个元素的大小排序;2、如何将两个有序集合合并成一个新的有序集合。第一个问题很好解决,那么第二个问题是否会很复杂呢?实际上第二个问题也很简单,只需要将两个集合同时进行一次遍历即可完成——比较当前集合中最小的元素,将最小元素放入新的集合,它的时间复杂度为O(n):
以下是归并排序算法的简单实现:
以上归并算法对1万条随机数进行排序只需要2-3毫秒,对10万条随机数进行排序只需要20毫秒左右的时间,对100万条随机数进行排序的平均时间大约为160毫秒(这还要看随机生成的待排序数组是否本身的凌乱程度)。可见归并算法本身是具有良好的性能的。使用JMX工具和操作系统自带的CPU监控器监视应用程序的执行情况,可以发现整个算法是单线程运行的,且同一时间CPU只有单个内核在作为主要的处理内核工作:
JMX中观察到的线程情况:
CPU的运作情况:
3-2. 使用Fork/Join运行归并算法
但是随着待排序集合中数据规模继续增大,以上归并算法的代码实现就有一些力不从心了,例如以上算法对1亿条随机数集合进行排序时,耗时为27秒左右。
接着我们可以使用Fork/Join框架来优化归并算法的执行性能,将拆分后的子任务实例化成多个ForkJoinTask任务放入待执行队列,并由Fork/Join框架在多个ForkJoinWorkerThread线程间调度这些任务。如下图所示:
以下为使用Fork/Join框架后的归并算法代码,请注意joinInts方法中对两个有序集合合并成一个新的有序集合的代码,是没有变化的可以参见本文上一小节中的内容。所以在代码中就不再赘述了:
使用Fork/Join框架优化后,同样执行1亿条随机数的排序处理时间大约在14秒左右,当然这还和待排序集合本身的凌乱程度、CPU性能等有关系。但总体上这样的方式比不使用Fork/Join框架的归并排序算法在性能上有30%左右的性能提升。以下为执行时观察到的CPU状态和线程状态:
JMX中的内存、线程状态:
CPU使用情况:
除了归并算法代码实现内部可优化的细节处,使用Fork/Join框架后,我们基本上在保证操作系统线程规模的情况下,将每一个CPU内核的运算资源同时发挥了出来。
- 线程基础:多任务处理(13)——Fork/Join框架(解决排序问题)
- 线程基础:多任务处理——Fork/Join框架(解决排序问题)
- 线程基础:多任务处理——Fork/Join框架(排序算法性能补充)
- 线程基础:多任务处理(16)——Fork/Join框架(排序算法性能补充)
- 线程基础:多任务处理(12)——Fork/Join框架(基本使用)
- 线程基础:多任务处理(14)——Fork/Join框架(要点1)
- 线程基础:多任务处理(15)——Fork/Join框架(要点2)
- 线程基础:多任务处理——Fork/Join框架(基本使用)
- 线程基础:多任务处理——Fork/Join框架(要点1)
- 线程基础:多任务处理——Fork/Join框架(要点2)
- Java7 Fork-Join 框架:任务切分,并行处理
- Java7 Fork-Join 框架:任务切分,并行处理
- Java7 Fork-Join 框架:任务切分,并行处理
- Fork/Join框架来并行执行任务
- 聊聊并发(八)——Fork/Join框架介绍
- 聊聊并发(八)——Fork/Join框架介绍
- 聊聊并发(八)——Fork/Join框架介绍
- 聊聊并发(八)——Fork/Join框架介绍
- poj1860Currency Exchange
- 最短路
- 1026:求s=a+aa+aaa+aaaa+aa..a的值
- 基于Spring的ApplicationContext获取方式
- Hadoop2.x HDFS架构图
- 线程基础:多任务处理——Fork/Join框架(解决排序问题)
- Servlet之Http协议(二)
- Java中 Int 和Integer 的区别
- #pragma clang diagnostic ignored 作用
- PAT乙级1040. 有几个PAT(25)
- JSON扫盲-JSON和spingmvc中的json格式传递
- Java中String三种加法的区别
- ubuntu下安装nginx服务器
- ECMAScript6 学习笔记