多线程分解串行工作
场景: 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();
}
}
优点:充分利用多核并行运算能力,缩短响应时间。
缺点:程序设计较复杂,业务代码要切割成互不影响的模块供线程调用,多线程序设计。
推荐阅读
-
简练软考知识点整理-创建工作分解结构过程 软考简练项目管理信息系统项目管理师信管
-
并发和并行 多线程算法活动Web工作
-
并发和并行 多线程算法活动Web工作
-
在DotNet1.1和2.0中一致地使用多线程 多线程工作
-
非技术(二)—— 机会成本 多线程生活Blog工作
-
简单了解Java多线程工作
-
分享我在工作中遇到的多线程下导致RCW无法释放的问题
-
python 多线程串行和并行的实例
-
多线程、同步工作原理、死锁案例、Lock接口、线程的生命周期的讲解及实现
-
VC++中多线程学习(MFC多线程)一(线程的创建、线程函数如何调用类成员呢?如何调用主对话框的成员?、MFC中的工作线程和界面线程的区别)