关于用多线程时任务分配与结果收集的问题的设计讨论
假定任务是这样的: 对于给定字符串,如“threadTest”, 给它再续上个“@”, 最后返回结果。 这些单条任务间没有任何的依赖关系。
假定这样的字符串很多, 如1000个, 而可以创建的线程数不能多于35个。
于是, 就有了线程创建后, 分配任务的问题, 怎么能在代码上优雅地把给定任务组,分配到线程池中, 然后再去收集这些线程处理后的结果?
想用java.util.concurrency中的Future, 可这个好像不能支持批量结果的收集吧?
于是, 用线程很原始地写了个粗暴分配任务与收集结果的代码, 这个很丑陋的。 大家说怎么改进,设计?
========下面是我粗陋实现的代码===========
Java代码
package rmn.thread;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TaskAssignAndResultCollection {
private final static int DEFAULT_THREAD_NUM = 5;
private int threadNum = DEFAULT_THREAD_NUM;
private Worker[] threads = null;
public TaskAssignAndResultCollection(int threadNum) {
super();
if (threadNum == 0) {
threadNum = DEFAULT_THREAD_NUM;
} else {
this.threadNum = threadNum;
}
}
public Map<String, String> processStringBatchly(
String[] datas) {
if (threads == null) {
synchronized (this) {
threads = new Worker[threadNum];
for(int i = 0 ; i < threadNum; i++) {
threads[i] = new Worker();
}
}
}
// 怎么把domainName分配给线程, 让它们自己运行去?平均分配,
int domainSize = datas.length;
int domainNamePerThread = domainSize / threadNum;
int leftDomainName = domainSize % threadNum;
List<String> listDomainName = Arrays.asList(datas);
//先每个线程平均地分domainNamePerThread个DomainName,
int endIndex = 0;
for (int i=0; i<threadNum; i++) {
int beginIndex = i * domainNamePerThread;
int step = domainNamePerThread;
endIndex = beginIndex + step;
List<String> subDomainNames = new ArrayList<String>(listDomainName.subList(beginIndex, endIndex));
threads[i].setDomainNameList(subDomainNames);
}
//然后,再把剩下的逐个分配。
for(int i=0; i< leftDomainName; i++) {
threads[i].addDomainName(listDomainName.get(endIndex + i));
}
for(Worker thread : threads ) {
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Map<String, String> totalResult = new HashMap<String, String>();
for(Worker thread : threads) {
totalResult.putAll(thread.getResultCollector());
}
return totalResult;
}
public static void main(String[] args) {
String[] datas = new String[] {"baidu.com", "sohu.com", "163.com", "iteye.com"};
TaskAssignAndResultCollection c = new TaskAssignAndResultCollection(3);
Map<String, String> resultCollector = c.processStringBatchly(datas);
补充:软件开发 , Java ,