假定任務是這樣的: 對於給定字符串,如“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);
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;
}
}