采用共享变量+Callable的方式
需求:将同步代码改成多线程
原始同步代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| JSONObject resultJson=new JSONObject();
patrolDevice.setHead_people_id_number(userService.getUserDetailAndCheckIdNumber(token)); List<PatrolDevice> results=patrolDeviceDao.queryDeviceByObjectNoPagination(patrolDevice); if(results.isEmpty() || results.size()>1){ throw new MissingArgumentException("本设备不属于当前登录人员的巡检任务"); } PatrolDevice resultDevice=results.get(0); if(resultDevice.getDevice_type()==null){ throw new MissingArgumentException("获取巡检任务类型异常,获取检查项失败,请完善巡检任务基础信息"); } long interval= TimeUtil.getExpireIntervalByExpireTime(resultDevice.getExpiry_time()); resultDevice.setExpire_interval(interval); List<PatrolCheckItem>resultItems=patrolCheckItemDao.queryCheckItemByTypeName(new PatrolDeviceType(resultDevice.getDevice_type())); AppUser resultUser = userService.getUserDetail(token);
resultJson.put("checkItem",resultItems); resultJson.put("taskDetail", resultDevice); resultJson.put("userDetail", resultUser); return resultJson;
|
改进成多线程方式
首先使用ExecutorService线程池固定生成三个线程:
但是,后两种线程需要第一个线程的执行结果,且三个线程需要共同将执行结果put到结果json类中,期间用户详情查询线程需要根据身份验证线程的返回结果作补充。
采用Future父类接受执行结果,利用get()函数阻塞,实现在身份验证线程执行完后,在异步执行后两种线程。自定义有参构造函数,实现参数的接续传递和共享。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| public JSONObject queryCheckTaskDetailByUserToken(String token, PatrolDevice patrolDevice) throws MissingArgumentException { JSONObject resultJson=new JSONObject();
ExecutorService executorService = Executors.newFixedThreadPool(3);
try { Future<PatrolDevice> futureIdentifier = executorService.submit(new IdentifierTask(patrolDevice,token)); PatrolDevice resultDevice=futureIdentifier.get(); Future<List<PatrolCheckItem>> futurePatrolTask = executorService.submit(new FetchPatrolTask(resultDevice,resultJson)); Future<AppUser> futureUser = executorService.submit(new FetchUserDetail(token,resultJson)); if(futurePatrolTask.get()==null && futureUser.get()==null){ return resultJson; } }catch (Exception e){ executorService.shutdown(); throw new MissingArgumentException(e.getMessage()); } return resultJson; }
class IdentifierTask implements Callable<PatrolDevice> { public PatrolDevice patrolDevice; public String token;
public IdentifierTask(PatrolDevice patrolDevice, String token) { this.patrolDevice = patrolDevice; this.token = token; } @Override public PatrolDevice call() throws Exception { patrolDevice.setHead_people_id_number(userService.getUserDetailAndCheckIdNumber(token)); List<PatrolDevice> results=patrolDeviceDao.queryDeviceByObjectNoPagination(patrolDevice); if(results.isEmpty() || results.size()>1){ throw new MissingArgumentException("本设备不属于当前登录人员的巡检任务"); } return results.get(0); } }
class FetchPatrolTask implements Callable<List<PatrolCheckItem>>{ public PatrolDevice resultDevice; public JSONObject resultJson;
public FetchPatrolTask(PatrolDevice resultDevice, JSONObject resultJson) { this.resultDevice = resultDevice; this.resultJson = resultJson; }
@Override public List<PatrolCheckItem> call() throws Exception { if(resultDevice.getDevice_type()==null){ throw new MissingArgumentException("获取巡检任务类型异常,获取检查项失败,请完善巡检任务基础信息"); } long interval= TimeUtil.getExpireIntervalByExpireTime(resultDevice.getExpiry_time()); resultDevice.setExpire_interval(interval); List<PatrolCheckItem>resultItems=patrolCheckItemDao.queryCheckItemByTypeName(new PatrolDeviceType(resultDevice.getDevice_type())); resultJson.put("checkItem",resultItems); resultJson.put("taskDetail", resultDevice); return null; } }
class FetchUserDetail implements Callable<AppUser> { public String token; public JSONObject resultJson;
public FetchUserDetail(String token, JSONObject resultJson) { this.token = token; this.resultJson = resultJson; }
@Override public AppUser call() throws Exception { AppUser resultUser = userService.getUserDetail(token); resultJson.put("userDetail", resultUser); return null; } }
|
性能测试
单线程10000次请求的压力测试,设定100ms的响应时间为标准:
|
通过 |
未通过 |
改进前 |
9106次 |
896次 |
改进后 |
9254 |
746 |
单线程100次压力测试,设定30ms的响应时间为标准
|
通过 |
未通过 |
改进前 |
53 |
47 |
改进后 |
58 |
42 |
单线程100次压力测试,设定10ms的响应时间为标准
|
通过 |
未通过 |
改进前 |
0 |
100 |
改进后 |
2 |
98 |
测试结果由于现场网络情况较差且不稳定原因,会有偏差,但是综合来看,改进后响应速度还是有提升,特别是在压力较大的情况下,提升较为明显。