1. 程式人生 > 其它 >@Async執行多執行緒傳送請求並監聽請求

@Async執行多執行緒傳送請求並監聽請求

場景:測試反應介面請求時比較慢,原因是因為第三方介面限制了請求時間為1天,但是接到的需要支援7天的查詢。

問題:單執行緒 例如查詢  2022-03-01 至 2022-03-07  ,

           1.把時間段拆成陣列["2022-03-01","2022-03-02",...."2022-03-07"]

           2.使用httpclien.get("2022-03-01 00:00:00","2022-03-01 23:59:59")  for迴圈依次查詢到7號

           3.合併結果集

這樣執行下來2.4W個軌跡點用了2.77s

解決及優化思路:   給成多執行緒

          1.把時間段拆成陣列["2022-03-01","2022-03-02",...."2022-03-07"]

          2.將每一天執行的httpclien視為一個Future,並放到陣列中佔位,這樣可以保證資料的返回的順序。

          3. 返回值放入 Future ,合併結果集

這樣執行下來2.4W個軌跡點用了1.5s

具體實現:

1.配置執行緒池引數 為XXXExecutor

fleet_executor:
  # 核心執行緒數:執行緒池建立時候初始化的執行緒數
  corePoolSize: 10
  # 最大執行緒數:執行緒池最大的執行緒數,只有在緩衝佇列滿了之後才會申請超過核心執行緒數的執行緒
  maxPoolSize:  20
  # 緩衝佇列:用來緩衝執行任務的佇列
  queueCapacity:  500
  # 允許執行緒的空閒時間60秒:當超過了核心執行緒之外的執行緒在空閒時間到達之後會被銷燬
  keepAliveSeconds: 60

 

2.@Async("XXXExecutor")修飾消費類

@Slf4j
@Service
public class CallServiceImpl implements CallService {

    @Value("${fms-http.tsp.ip}")
    private String ipAdd;
    @Value("${fms-http.tsp.token}")
    private String token;
    @Value("${fms-http.tsp.http}")
    private String http;


    @Override
    
// 指定使用beanname為callTspExecutor的執行緒池 @Async("FleetExecutor") public Future<String> tspByKeyAsync(String apiKey, Map<String, String> params) { String url = ApiList.getFotonAPIConfig(apiKey); String rqUrl = String.format("%s://%s%s?token=%s", http, ipAdd, url, token); try { return new AsyncResult<>(HttpClientUtils.get(rqUrl, params, null)); } catch (Exception e) { log.error(e.getMessage(), e); return new AsyncResult<>("{\"type\" : \"error\",\"success\" : \"false\",\"content\" : \"讀取異常!\"}"); } } }

呼叫方

@Override
    public List<CarLineDetailVo> getTspHisLocationsV2(String vin, Date startDate, Date endDate) throws Exception {
        List<Future<String>> futures = Lists.newArrayList();
        List<CarLineDetailVo> voList = Lists.newArrayList();
        List<Pair<Date, Date>> list = DateUtils.partitionByDay(startDate, endDate, 1);
        for (Pair<Date, Date> pair : list) {
            String startTime = DateUtils.toString(pair.getKey(), DateUtils.DEFAULT_DATE_TIME_FORMAT);
            String endTime = DateUtils.toString(pair.getValue(), DateUtils.DEFAULT_DATE_TIME_FORMAT);
            futures.add(callService.tspByKeyAsync(ApiList.CAR_HIS_LOCATION_INFO, ImmutableMap.of("idCode", vin, "startDate", startTime, "endDate", endTime)));
        }

        for (Future<String> future : futures) {
            String jsonStr = future.get();
            JSONObject rep = JSONObject.parseObject(jsonStr);
            try {
                isValid(rep);
            } catch (Exception e) {
                continue;
            }
            JSONArray arrData = rep.getJSONArray("data");
            voList.addAll(arrData.toJavaList(CarLineDetailVo.class));
        }
        return voList;
    }

3.合併結果(按需而定)

...