项目背景:前端发送一次请求,后台通过远程连接技术grpc获取数据。在一次请求中分多次请求grpc服务端,且请求为单线程,需要等待上一次请求结束后再发送请求,严重影响性能。
解决方案:采用多线程并发发送多个请求。
解决步骤:
1:创建线程连接池:
private ExecutorService threadPool = Executors.newFixedThreadPool(10);
2:获取需要发送请求的次数
使用 CountDownLatch ,判断所有线程是否执行完毕
final CountDownLatch latch = new CountDownLatch(num);
CountDownLatch 有两个方法,countDown(),数值 减1
await(),当CountDownLatch的值为0时,程序继续执行,否则程序阻塞
3:使用线程
由于需要得到远程连接的返回值,这边使用Callable接口获取返回值。
try {
Future res = threadPool.submit(new Callable<StatisticsCount.StatisticsCountResVo>() {
@Override
public StatisticsCount.StatisticsCountResVo call() throws Exception {
return stub.getCountInfo(rpcVo);
}
});
try {
return res;
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage());
logger.error("获取rpc结果失败");
}
} finally {
latch.countDown();
logger.info("lanthc:" + latch.getCount() + "--fp:" + fp);
}
new Callable<StatisticsCount.StatisticsCountResVo>() 可以自定义返回值类型,同时CountDownLatch的值减一,同时唤醒阻塞的线程。
3:获取线程的返回值
Future<StatisticsCount.StatisticsCountResVo> res= sendBaseSpecs(threadPool, rpcVo, latch, stub, statisticsCountVo.getFp(), base);
latch.await();
base = res.get();
其中,latch.await() 一直阻塞直到latch的值为0且所有线程执行完毕,但是不能保证线程是否有返回,通过res.get() 一直阻塞,直到获取到返回值,程序才继续往下面执行
上述使用方式存在问题:
1.线程池创建方式存在巨大隐患
2.Future.get() 获取方案存在超时隐患