分治,本质上就是繁而化简,大而化小。分治思想,是一种有效的解决复杂问题的编程思想;
Fork/Join线程池,Java 7开始引入,它可以执行一种特殊的任务:把一个大任务拆成多个小任务,并行执行,最后合并结果得到最终结果。这也是一种基于“分治”的算法。
案例:
假设我们要求一个Long数组的数据之和,这个数组非常大,怎么做呢?
一种常规的做法,就是在一个单独的线程里,用一个循环累加求和,有没有更好的方法呢?
还有就是要说的Fork/Join线程池了,基于分治思想,把大数组拆分成足够小的数组,然后同时跑多个线程并行计算小数组的和,再累加小数组的和得到最终的和;
Java代码案例如下:
package leetcode;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
public class DivideAndConquerDemo {
public static void main(String[] args) {
// 创建大数组并填充数据:
long[] array = new long[90000000];
for (int i = 0; i < array.length; i++) {
array[i] = random();
}
long result = 0;
//非分治算法统计数组数据之和
long startTime = System.currentTimeMillis();
for(int i=0;i<array.length;i++) {
result += array[i];
}
long endTime = System.currentTimeMillis();
System.out.println("非分治算法计算结果, sum: " + result + " in " + (endTime - startTime) + " ms");
//分治算法统计数组数据之和, fork/join:
ForkJoinTask<Long> task = new SumTask(array, 0, array.length);
startTime = System.currentTimeMillis();
result = ForkJoinPool.commonPool().invoke(task);
endTime = System.currentTimeMillis();
System.out.println("分治算法计算结果,sum: " + result + " in " + (endTime - startTime) + " ms");
}
static Random random = new Random(0);
static long random() {
return random.nextInt(10000);
}
}
class SumTask extends RecursiveTask<Long> {
static final int THRESHOLD = 50000;
long[] array;
int start;
int end;
SumTask(long[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if (end - start <= THRESHOLD) {
// 如果任务足够小,直接计算:
long sum = 0;
for (int i = start; i < end; i++) {
sum += this.array[i];
}
return sum;
}
// 任务太大,一分为二:
int middle = (end + start) / 2;
SumTask subtask1 = new SumTask(this.array, start, middle);
SumTask subtask2 = new SumTask(this.array, middle, end);
invokeAll(subtask1, subtask2);
Long subresult1 = subtask1.join();
Long subresult2 = subtask2.join();
Long result = subresult1 + subresult2;
return result;
}
}
测试的一组log如下:
非分治算法计算结果, sum: 449987569580 in 54 ms
分治算法计算结果,sum: 449987569580 in 48 ms
分治思想的应用非常多,实际工作中也常遇到,分治思想是我们编程的一种有效的思想武器。