1. 程式人生 > 實用技巧 >多執行緒拆分list,合併list

多執行緒拆分list,合併list

今天有一個介面20s 才能展示出來資料,這怎麼可以領導直接讓我去處理這個介面,處理不出來就不要下班了

我心中一緊 趕緊去看這是哪個垃圾寫出來的程式碼

瀏覽了一下程式碼發現 需求是這樣子的 後臺請求一個地址 返回了一個list集合,我拿著這個list 集合物件的主鍵,再去呼叫檢視詳情介面,拼接到原來的物件上。最後在合併拼接上引數的物件集合。

以前的兄弟直接for迴圈呼叫,資料量不大 130多條資料 但是也需要20秒(1個介面呼叫150毫秒,幫大家算出來了)。

這怎麼行,祭出大殺器,多執行緒。

我們需要用callable 的執行緒方法 因為我們還需要將返回值 給他拼回去 程式碼如下

package com.zhgw.dev.pioc.utils;

import com.alibaba.fastjson.JSONObject; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; public class PersionThread implements Callable { /** 資料集合 */ private List<PersionDTO> list; /** 許可權 */ private
String token; /** 每個執行緒處理的起始資料 */ private CountDownLatch begin; /** 每個執行緒處理的結束資料 */ private CountDownLatch end; public PersionThread() { } public PersionThread(List<PersionDTO> list, CountDownLatch begin, CountDownLatch end,String token) { this.list = list;
this.begin = begin; this.end = end; this.token = token; } @Override public List<PersionDTO> call() throws Exception { try { if (list != null && !list.isEmpty()) { // testBatchInsertMapper.batchInsert(list); List<PersionDTO> PersionDTOArrayList = new ArrayList<>(); int size = list.size(); for (PersionDTO PersionDTO :list) { String personString = HttpUtils.httpPostForm("http://www.baidu.com" + "?token=" + token + "&oid=" + PersionDTO.getInspectoroid(), null, false, "160"); } //System.out.println("執行緒"+JSONObject.toJSONString(PersionDTOArrayList)); return PersionDTOArrayList; } // 執行完讓執行緒直接進入等待 begin.await(); } catch (Exception e) { e.printStackTrace(); } finally { // 當一個執行緒執行完 了計數要減一不然這個執行緒會被一直掛起 end.countDown(); } return null; } }

執行多執行緒的方法

public  List batchInsertByThread(List<PersionDTO> list, String token){

        if (list == null || list.isEmpty()) {
            return null;
        }
        // 一個執行緒處理6條資料
        int count = 7;
        // 資料集合大小
        int listSize = list.size();
        // 開啟的執行緒數
        int runSize = (listSize / count) + 1;
        // 存放每個執行緒的執行資料
        List<PersionDTO> newList = null;
        // 建立一個執行緒池,數量和開啟執行緒的數量一樣
        ExecutorService executor = Executors.newFixedThreadPool(runSize);
        // 建立兩個個計數器
        CountDownLatch begin = new CountDownLatch(1);
        CountDownLatch end = new CountDownLatch(runSize);
        List<Future< List<PersionDTO>>> futures = new ArrayList<Future< List<PersionDTO>>>();
        // 建立一個儲存所有返回值的list
        List<PersionDTO> listAll = Collections.synchronizedList(new ArrayList<PersionDTO>());

        for (int i = 0; i < runSize; i++) {
            /* 計算每個執行緒執行的資料 */
            if ((i + 1) == runSize) {
                int startIdx = (i * count);
                int endIdx = list.size();
                newList = list.subList(startIdx, endIdx);
            } else {
                int startIdx = (i * count);
                int endIdx = (i + 1) * count;
                newList = list.subList(startIdx, endIdx);
            }
            PersionThread PersionThread = new PersionThread(newList, begin, end, token);
            futures.add(executor.submit(PersionThread));
        }
        begin.countDown();
        //System.out.println("submit"+ JSONObject.toJSONString(submit));
        try {
            for(Future< List<PersionDTO>> future : futures){
                //合併操作
                List<PersionDTO> PersionDTOS = null;
                try {
                    PersionDTOS = future.get();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
                listAll.addAll(PersionDTOS);
            }
            //System.out.println(JSONObject.toJSONString(listAll));
            end.await();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executor.shutdown();
        return listAll;
    }

呼叫執行緒的方法

public static void main(String[] args) {
        R<List<PersonnelGPSDTO>> listR = personnelGPS();
        System.out.println(listR);