1. 程式人生 > >使用執行緒池與CountDownLatch多執行緒提升系統性能

使用執行緒池與CountDownLatch多執行緒提升系統性能

下面這個業務場景,大家可能都會遇到,在遍歷一個list的時候,需要對list中的每個物件,做一些複雜又耗時的操作,比如取出物件的uid,遠端呼叫一次userservice的getUserByUid方法,這屬於IO操作了,可怕的是遍歷到每個物件時,都得執行一次這種RPC的IO操作(甚至不止一次,因為可能還有別的介面需要去調)還有複雜的業務邏輯需要cpu去計算。

以上這種場景,屬於IO操作和CPU操作混合,如果是純IO操作的話,也是可以用這種方案來解決的,因為一個執行緒向遠端伺服器發出請求了,再等待響應的過程中,其他執行緒也可以向遠端伺服器發出請求(請求-請求-響應-響應),這樣也比請求-響應-請求-響應 這種模式要快。

下面貼上一個小demo,供大家參考。
ExecutorService作為一個執行緒池,然後利用CountDownLatch可以讓指定數量的執行緒都執行完再執行主執行緒的特性。就可以實現多執行緒提速了。
套路是這樣的:
1、實現runnable介面實現一個run方法,裡面執行我們的耗時複雜業務操作。
2、在迴圈裡給list裡的每個物件分配一個執行緒
3、使用CountDownLatch讓主執行緒等待工作執行緒全部執行完畢後之後,再繼續執行。


這裡寫程式碼片
//多核定製執行緒池
static ExecutorService taskPool = ExecutorUtils.newMultiCpuFlexibleThreadPool(5, “task-pool”);

//為了提高效能,耗時的業務邏輯操作做使用多執行緒處理
public class RunnerTask implements Runnable {
    private EnumSet<GoodsMsgEnum.property> goodProperty;
    private List<GoodAllMsg> resultList;
    private UserApply item;
    private String logStr;
    private CountDownLatch latch;
    public RunnerTask(List<GoodAllMsg> resultList,UserApply item,EnumSet<GoodsMsgEnum.property> goodProperty,String logStr,CountDownLatch latch) {
        this.resultList=resultList;
        this.item=item;
        this.goodProperty=goodProperty;
        this.logStr=logStr;
        this.latch=latch;

    }
    @Override
    public void run() {
        try {
            GoodAllMsg aa = goodsById(item.getInfoId(), goodProperty, logStr);
            if(aa!=null){
                aa.setAuditType(GlobalsDataCache.sysStatus.get(GlobalsVar.GOOD_AUDIT_STATUS_ACTIVE_PREFIX+item.getStatus()));
                addTotalList(resultList,aa);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(this.latch!=null){
                latch.countDown();
            }
        }
    }

}

private synchronized void addTotalList(List<GoodAllMsg> resultList,GoodAllMsg item){
    resultList.add(item);
}

/**
 * 多執行緒處理業務邏輯,提升效能
 * @param taskList 任務佇列
 * @param resultList  結果集
 * @param goodProperty
 * @param logStr
 */
public List<GoodAllMsg> multiThreadProcess(List<UserApply> taskList,List<GoodAllMsg> resultList,EnumSet<GoodsMsgEnum.property> goodProperty,String logStr) throws InterruptedException {
    if(taskList!=null && !taskList.isEmpty()){
        //建立閉鎖,計數器大小為任務多列的長多
        CountDownLatch latch=new CountDownLatch(taskList.size());
        for(UserApply item:taskList){
            //把閉鎖物件傳入執行緒中,並在執行緒的finally代買塊中將閉鎖計數器減一
            RunnerTask runnerTask=new RunnerTask(resultList,item,goodProperty,logStr,latch);
            taskPool.execute(runnerTask);
        }
        //主執行緒開始等待,直到計數器大小為0,返回結果
        latch.await();
        return resultList;
    }
    return new ArrayList<GoodAllMsg>();
}