2025-05-25

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

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *