前提:java中一個接口的實現如果是基於組裝多個不同系統之間的數據(並且多個系統之間數據的獲取沒有關聯性),那麼此時就可以通過異步請求的方式來實現性能優化。
實現性能優化原理剖析:
例如實現一個接口需要調用3個系統的數據,a系統的請求時間爲1s,b系統的請求時間爲2s,c系統的請求時間爲3s,那麼使用單線程完成一次接口調用的總時間至少爲1+2+3=6s。使用多線程異步調用接口的時間大約爲c系統請求的最長時間3s。
java中的具體實現:
需求:根據事業部門人數數量和營業部部門人數數量分別獲取事業部門的係數和營業部門的係數,而獲取事業部門係數和營業部門係數分別調用兩個接口,具體實現如下:
@Service public class EmpInfoServiceImpl implements EmpInfoService { private static Logger logger = LoggerFactory.getLogger(EmpInfoServiceImpl.class); ExecutorService executor = Executors.newCachedThreadPool(); @Autowired (required = false) private OrgService orgService; @Autowired private EmpService empService; @Autowired private AreaRatioService areaRatioService; @Autowired private SalesOfficeRatioDao salesOfficeRatioDao; @Override public EmpInfo getEmpAscriptionByCode(String code) { EmpInfo empInfo = new EmpInfo(); BaseResult<OrgRegionDeptTeam> result = orgService.getEmpORDTInfoByCode(code); if(BaseResult.success().getStatus().equals(result.getStatus())){//獲取請求成功 OrgRegionDeptTeam orgRegionDeptTeam = result.getData(); //設置大區信息 empInfo.setAreaCode(orgRegionDeptTeam.getRegionCode()); empInfo.setAreaName(orgRegionDeptTeam.getRegionName()); empInfo.setAreaPersonCode(orgRegionDeptTeam.getRegionLeaderCode()); if(StringUtils.isNotBlank(empInfo.getAreaCode())){ AreaRatio areaRatio = new AreaRatio(); areaRatio.setCode(empInfo.getAreaCode()); areaRatio.setArea(empInfo.getAreaName()); AreaRatio area = areaRatioService.findOne(areaRatio); if(area != null) { empInfo.setAreaRatio(new BigDecimal(area.getRatio())); }else{ empInfo.setAreaRatio(null); } } empInfo.setAreaPersonName(orgRegionDeptTeam.getRegionLeaderName()); //設置事業部信息 empInfo.setBusinessUnitCode(orgRegionDeptTeam.getDivisionCode()); empInfo.setBusinessUnitName(orgRegionDeptTeam.getDivisionName()); empInfo.setBusinessUnitPersonCode(orgRegionDeptTeam.getDivisionLeaderCode()); empInfo.setBusinessUnitPersonName(orgRegionDeptTeam.getDivisionLeaderName()); //設置營業部信息 empInfo.setSalesOfficeCode(orgRegionDeptTeam.getDeptCode()); empInfo.setSalesOfficeName(orgRegionDeptTeam.getDeptName()); empInfo.setSalesOfficePersonCode(orgRegionDeptTeam.getDeptLeaderCode()); empInfo.setSalesOfficePersonName(orgRegionDeptTeam.getDeptLeaderName()); //設置團隊信息 empInfo.setTeamCode(orgRegionDeptTeam.getTeamCode()); empInfo.setTeamName(orgRegionDeptTeam.getTeamName()); empInfo.setPersonCode(orgRegionDeptTeam.getCode()); //根據事業部人數數量獲取部門係數 FutureTask<BigDecimal> businessUnitFutureTask =null; if(StringUtils.isNotBlank(empInfo.getBusinessUnitCode())){ businessUnitFutureTask = new FutureTask<BigDecimal>(new Callable<BigDecimal>() { @Override public BigDecimal call() throws Exception { Integer personNum = empService.getDeptAndSubDeptUserCount(empInfo.getBusinessUnitCode()); return salesOfficeRatioDao.selectRatioByCountAndType(SalesOfficeRatio.BUSINESS_DEPT_TYPE,personNum); } }); executor.submit(businessUnitFutureTask); } // 根據營業部人數數量獲取部門係數 FutureTask<BigDecimal> salesOfficeFutureTask =null; if(StringUtils.isNotBlank(empInfo.getSalesOfficeCode())){ salesOfficeFutureTask = new FutureTask<BigDecimal>(new Callable<BigDecimal>() { @Override public BigDecimal call() throws Exception { Integer personNum = empService.getDeptAndSubDeptUserCount(empInfo.getSalesOfficeCode()); return salesOfficeRatioDao.selectRatioByCountAndType(SalesOfficeRatio.SALEOFFICE_DEPT_TYPE,personNum); } }); executor.submit(salesOfficeFutureTask); } BigDecimal businessUnitRation = null; BigDecimal salesOfficeRation = null; try { businessUnitRation = businessUnitFutureTask.get(); salesOfficeRation = salesOfficeFutureTask.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } empInfo.setSalesOfficeRatio(salesOfficeRation); empInfo.setBusinessUnitRatio(businessUnitRation!=null?businessUnitRation.toString():null); return empInfo; }else{ return null; } } }
總結:通過Executors生成的線程池、Callable和FutureTask來實現異步接口請求的調用,減少接口請求數據的響應時間,提升用戶體驗。