思路:把所有数据分组,每组使用一个线程去计算结果,计算完后再把结果汇总
具体实现如下:
1、用数据模拟文本里的数据
2、声明一个线程池和实现一个可返回结果的Callable接口
3、把果返回结果Future放到CopyOnWriteArrayList中用于结果集计算
4、此算法的缺点有待改进的地方是结果汇总时是被动去检测,而不是某个结果计算完成后主动去汇总,既然是分段计算,如果数据量足够大时,应该采用递归去实现分段汇总会更好
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package thread;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @description
*
* @author chenzehe
* @email hljuczh@163.com
* @create 2013-3-8 上午12:20:27
*/
public class CalculateTest {
public static void main(String[] args) {
int[] intNums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
System.out.println("Calculate start...");
System.out.println("Calculate result:" + Calculate.calculate(intNums));
System.out.println("Calculate finished.");
}
}
class Calculate {
static int poolSize = 5;
static ExecutorService executor = Executors.newFixedThreadPool(2);
/**
*
* @param targetNum
* @return
* @description 使用多线程对targetNum数组求和
* @author chenzehe
* @todo
*/
public static int calculate(int[] targetNum) {
int result = 0;
try {
// 返回结果Future放到CopyOnWriteArrayList中用于结果集计算
List<Future<Integer>> futures = new CopyOnWriteArrayList<Future<Integer>>();
for (int i = 0; i < poolSize; i++) {
// 提交任务
futures.add(executor.submit(new CalculateCallable(targetNum, poolSize, i)));
}
// 等待返回结果
while (true) {
if (futures.size() == 0) {
break;// 全部返回则跳出
}
for (Future<Integer> future : futures) {
System.out.println("waiting...");
if (future.isDone()) {
result += future.get();
futures.remove(future);// 有返回结果就移出
}
}
}
executor.shutdown();
}
catch (Exception ex) {
ex.printStackTrace();
}
return result;
}
}
class CalculateCallable implements Callable<Integer> {
int[] targetNum;
int threadNum;
int poolSize;
public CalculateCallable(int[] targetNum, int poolSize, int threadNum) {
this.targetNum = targetNum;
this.poolSize = poolSize;
this.threadNum = threadNum;
}
@Override
public Integer call() {
// 根据某种算法算出这里需要读取某部分数据,此处只是简单平均
int result = 0;
int eachSize = (targetNum.length + poolSize) / poolSize;
int start = eachSize * threadNum;
int end = start + eachSize;
for (int i = start; i < end && i < targetNum.length; i++) {
result += targetNum[i];
}
try {
// 模拟长时间的运算
Thread.sleep(3000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
}
此解决方案缺点现已使用JDK7中Fork-Join模式解决。