场景: LIST页面,商品由A和B商品组成,A和B商品分别在不同的search,需要调用两次请求组装后返回渲染。
优点:路径简单,程序实现容易
缺点:无法发挥机器多核并行潜力
并行请求:
设计思路:
互相不依赖的串行调用切割成多个单独方法。
利用线程池并行计算,用ExecutorService实现
全部线程运行完毕组装结果返回,用CountDownLatch实现
如果线程满了,并发不被池接受,则调用同步方法,不影响功能实现。
注意:
高并发时executorService.execute 可能抛RejectedExecutionException,是当前任务不被线程池接受异常
需要在Runnable中有方法处理,并做cd.countDown();
否则会被cd.await()阻塞。
publicclass ConcurrentSearchService implements InitializingBean {
protected Logger log = LoggerFactory
.getLogger(ConcurrentSearchService.class);
private SearchService searchService;
private ExecutorService executorService;
/**
* 线程池的核心线程数量
*/
privateintcoreThreadCount;
/**
* 线程池的最大线程数量
*/
privateintmaxThreadCount;
/**
* 线程池中空闲线程的存活时间,单位秒
*/
privatelongaliveTime;
privateintACTIONS = 2;
public SearchResultDO doSearch() {
SearchResultDO searchResultDO = new SearchResultDO();
CountDownLatch cd = new CountDownLatch(2);
for (int i = 1; i <= ACTIONS; i++) {
executeRunnable(i, cd, searchService, searchResultDO);
}
try {
cd.await();
} catch (InterruptedException ie) {
// 其实不太可能被中断.
thrownew RuntimeException(ie);
}
return searchResultDO;
}
privatevoid executeRunnable(int actionType, CountDownLatch cd,
SearchService searchService, SearchResultDO searchResultDO) {
SearchEngineRunnable searchEngineRunnable = new SearchEngineRunnable(
actionType, cd, searchService, searchResultDO);
try {
executorService.execute(searchEngineRunnable);
} catch (RejectedExecutionException exception) { //
// TODO: handle exception
searchEngineRunnable.threadErrorHandle();
log.error("threadErrorHandle");
}
}
publicvoid afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
if (this.coreThreadCount == 0) {
this.coreThreadCount = 50;
}
if (this.maxThreadCount == 0) {
this.maxThreadCount = 300;
}
if (this.aliveTime == 0L) {
this.aliveTime = 30L;
}
executorService = new ThreadPoolExecutor(this.coreThreadCount,
this.maxThreadCount, this.aliveTime, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
}
publicclass SearchEngineRunnable implements Runnable {
privateintactionType;
private CountDownLatch cd;
private SearchService searchService;
private SearchResultDO searchResultDO;
public SearchEngineRunnable(int actionType,CountDownLatch cd,SearchService searchService,SearchResultDO searchResultDO){
this.actionType = actionType;
this.cd = cd;
this.searchService = searchService;
this.searchResultDO = searchResultDO;
}
publicvoid run() {
// TODO Auto-generated method stub
blockHandle();
cd.countDown();
}
privatevoid blockHandle(){
if(actionType == 1){
searchResultDO.setAItems(searchService.c2cSearch());
}else{
searchResultDO.setBItems(searchService.tmallSearch());
}
}
publicvoid threadErrorHandle() {
// TODO Auto-generated method stub
blockHandle();
cd.countDown();
}
}
优点:充分利用多核并行运算能力,缩短响应时间。
缺点:程序设计较复杂,业务代码要切割成互不影响的模块供线程调用,多线程序设计。