假定任务是这样的: 对于给定字符串,如“threadTest”, 给它再续上个“@”, 最后返回结果。 这些单条任务间没有任何的依赖关系。
假定这样的字符串很多, 如1000个, 而可以创建的线程数不能多于35个。
于是, 就有了线程创建后, 分配任务的问题, 怎么能在代码上优雅地把给定任务组,分配到线程池中, 然后再去收集这些线程处理后的结果?
想用java.util.concurrency中的Future, 可这个好像不能支持批量结果的收集吧?
于是, 用线程很原始地写了个粗暴分配任务与收集结果的代码, 这个很丑陋的。 大家说怎么改进,设计?
========下面是我粗陋实现的代码===========
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);
c.showMsg(resultCollector);
}
private void showMsg(Map<String, String> result) {
for(Map.Entry<String, String> me : result.entrySet()) {
String data = me.getKey();
String r = me.getValue();
String msg = "原始值[" + data + "]" + " 处理后[" + r + "]" ;
System.out.println(msg);
}
}
}
class Worker extends Thread {
private List<String> datas;
private Map<String, String> resultCollector = new HashMap<String, String>();
public void run() {
for (String d : datas) {
String result = d + "@";
resultCollector.put(d, result);
}
}
public void setDomainNameList(List<String> subDomainNames) {
datas = subDomainNames;
}
public void addDomainName(String domainName) {
if (datas == null ) {
datas = new ArrayList<String>();
}
datas.add(domainName);
}
public Map<String, String> getResultCollector() {
return resultCollector;
}
}