Java 7并行执行并没有使用倒计时锁存器提高REST API的性能
我正在用Java7编写一个RESTAPI,从数据库中检索三个项目,并将这三个项目作为响应一起发送给用户。当程序在顺序流中运行时,即,如果我先获取一个项目,然后获取另一个项目,则执行该项目需要合理的时间。但是,当我使用多线程时,即使用三个线程从数据库中获取三个项目,与顺序执行相比,执行需要更多的时间。此问题导致CPU使用率高达90%以上。 例如:Java 7并行执行并没有使用倒计时锁存器提高REST API的性能,java,multithreading,rest,parallel-processing,countdownlatch,Java,Multithreading,Rest,Parallel Processing,Countdownlatch,我正在用Java7编写一个RESTAPI,从数据库中检索三个项目,并将这三个项目作为响应一起发送给用户。当程序在顺序流中运行时,即,如果我先获取一个项目,然后获取另一个项目,则执行该项目需要合理的时间。但是,当我使用多线程时,即使用三个线程从数据库中获取三个项目,与顺序执行相比,执行需要更多的时间。此问题导致CPU使用率高达90%以上。 例如: Sequential: number of users 60 average execution time-
Sequential: number of users 60
average execution time- 5149 milliseconds
Parallel: number of users 60
average execution time- 9544 milliseconds
我使用ExecutorService来实现异步执行机制,并使用倒计时锁存器来同步线程
为什么并行执行比顺序执行花费更多的时间?这里使用倒计时闩锁有什么缺点吗
使用倒计时锁存器执行辅助线程的代码:
List<Runnable> workers;
if (StringUtils.isBlank(typeCode)) {
workers =
ItemManagerHelper.determineItemLookupWorkersByItemIdentifiers(Id, ids,
effectiveStartDate, effectiveEndDate, errors, ItemUIList, dataMap);
}
else {
workers = ItemManagerHelper.determineItemLookupWorkersByItemType(Id,
ids,effectiveStartDate,effectiveEndDate, typeCode, errors, ItemUIList,
dataMap);
}
ExecutorService threadPoolExecutor = Executors.newFixedThreadPool
(workers.size());
CountDownLatch latch = new CountDownLatch(workers.size());
for (Runnable worker : workers) {
((ItemLookupThread) worker).setLatch(latch);
threadPoolExecutor.submit(worker);
}
try {
latch.await(threadTimeOut, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e) {
error(this.getClass(), e, "Exception occurred while waiting for the
lookup child threads completion.");
}
finally {
threadPoolExecutor.shutdown();
}
列出工人名单;
if(StringUtils.isBlank(类型代码)){
工人=
ItemManagerHelper.通过ItemIdentifiers(Id、Id、,
有效开始日期、有效结束日期、错误、项目列表、数据映射);
}
否则{
workers=ItemManagerHelper.DeterminiteItemLookupWorkers ByItemType(Id,
ID、有效开始日期、有效结束日期、类型代码、错误、ItemUIList、,
数据地图);
}
ExecutorService threadPoolExecutor=Executors.newFixedThreadPool
(workers.size());
CountDownLatch latch=新的CountDownLatch(workers.size());
for(可运行工作程序:工作程序){
((ItemLookupThread)worker);
threadPoolExecutor.submit(worker);
}
试一试{
等待(线程超时,时间单位为毫秒);
}
捕捉(中断异常e){
错误(this.getClass(),e,“在等待
查找子线程完成。“);
}
最后{
threadPoolExecutor.shutdown();
}
ItemLookupThread是我的线程类:
public class ItemLookupThread implements Runnable {
private ItemProvider provider;
private long Id;
ItemsIdentifiers ids;
private long effectiveStartDate;
private long effectiveEndDate;
private Map<Object, Object> dataMap;
private List<BaseResponse.Error> errors;
private List<ItemUI> Items;
private CountDownLatch latch;
public ItemLookupThread (ItemProvider provider, long Id,
ItemsIdentifiers ids,long effectiveStartDate,
long effectiveEndDate, Map<Object, Object> dataMap,
List<ItemUI> Items, List<BaseResponse.Error> errors) {
this.provider = provider;
this.Id = Id;
this.ids = ids;
this.effectiveStartDate = effectiveStartDate;
this.effectiveEndDate = effectiveEndDate;
this.dataMap = dataMap;
this.Items = Items;
this.errors = errors;
}
@Override
public void run() {
try {
debug(this.getClass(), "Item lookup started :" +
Thread.currentThread().getId());
provider.lookup(Id, ids, effectiveStartDate, effectiveEndDate,
dataMap, Items, errors);
debug(this.getClass(), "Item lookup completed :" +
Thread.currentThread().getId());
}
finally {
if (latch != null) {
latch.countDown();
}
}
}
public void setLatch(CountDownLatch latch) {
this.latch = latch;
}
}
公共类ItemLookupThread实现可运行{
私人物品提供者;
私人长Id;
项目标识符ID;
私人长期有效起始日期;
私人长期有效终止日期;
私有地图数据地图;
私有列表错误;
私人清单项目;
私人倒计时闩锁;
公共ItemLookupThread(ItemProvider提供程序,长Id,
ItemSidentiers ID,长有效起始日期,
long effectiveEndDate,映射数据映射,
列出项目,列出错误){
this.provider=提供者;
这个.Id=Id;
this.ids=ids;
this.effectiveStartDate=effectiveStartDate;
this.effectiveEndDate=effectiveEndDate;
this.dataMap=dataMap;
这个。项目=项目;
这个。错误=错误;
}
@凌驾
公开募捐{
试一试{
调试(this.getClass(),“已开始项查找:”+
Thread.currentThread().getId());
查找(Id、Id、effectiveStartDate、effectiveEndDate、,
数据映射、项目、错误);
调试(this.getClass(),“项查找已完成:”+
Thread.currentThread().getId());
}
最后{
如果(闩锁!=null){
倒计时();
}
}
}
公共无效设置闩锁(倒计时闩锁){
this.latch=闩锁;
}
}
我猜有大量的上下文切换正在进行。我的建议是将ExecutorService从方法变量移动到服务(或控制器)类中的字段
private ExecutorService threadPoolExecutor=Executors.newFixedThreadPool(20);
public void myServiceMethod(){
列出工人名单;
if(StringUtils.isBlank(类型代码)){
工人=
ItemManagerHelper.通过ItemIdentifiers(Id、Id、,
有效开始日期、有效结束日期、错误、项目列表、数据映射);
}
否则{
workers=ItemManagerHelper.DeterminiteItemLookupWorkers ByItemType(Id,
ID、有效开始日期、有效结束日期、类型代码、错误、ItemUIList、,
数据地图);
}
CountDownLatch latch=新的CountDownLatch(workers.size());
for(可运行工作程序:工作程序){
((ItemLookupThread)worker);
threadPoolExecutor.submit(worker);
}
试一试{
等待(线程超时,时间单位为毫秒);
}
捕捉(中断异常e){
错误(this.getClass(),e,“在等待
查找子线程完成。“);
}
最后{
threadPoolExecutor.shutdown();
}
}
我猜有大量的上下文切换正在进行。我的建议是将ExecutorService从方法变量移动到服务(或控制器)类中的字段
private ExecutorService threadPoolExecutor=Executors.newFixedThreadPool(20);
public void myServiceMethod(){
列出工人名单;
if(StringUtils.isBlank(类型代码)){
工人=
ItemManagerHelper.通过ItemIdentifiers(Id、Id、,
有效开始日期、有效结束日期、错误、项目列表、数据映射);
}
否则{
workers=ItemManagerHelper.DeterminiteItemLookupWorkers ByItemType(Id,
ID、有效开始日期、有效结束日期、类型代码、错误、ItemUIList、,
数据地图);
}
CountDownLatch latch=新的CountDownLatch(workers.size());
for(可运行工作程序:工作程序){
((ItemLookupThread)worker);
threadPoolExecutor.submit(worker);
}
试一试{
等待(线程超时,时间单位为毫秒);
}
捕捉(中断异常e){
错误(this.getClass(),e,“在等待
查找子线程完成。“);
}
最后{
threadPoolExecutor.shutdown();
}
}
请分享更多详细信息-代码片段、您更改了什么、您如何使用闩锁、线程在做什么等等
private ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(20);
public void myServiceMethod() {
List<Runnable> workers;
if (StringUtils.isBlank(typeCode)) {
workers =
ItemManagerHelper.determineItemLookupWorkersByItemIdentifiers(Id, ids,
effectiveStartDate, effectiveEndDate, errors, ItemUIList, dataMap);
}
else {
workers = ItemManagerHelper.determineItemLookupWorkersByItemType(Id,
ids,effectiveStartDate,effectiveEndDate, typeCode, errors, ItemUIList,
dataMap);
}
CountDownLatch latch = new CountDownLatch(workers.size());
for (Runnable worker : workers) {
((ItemLookupThread) worker).setLatch(latch);
threadPoolExecutor.submit(worker);
}
try {
latch.await(threadTimeOut, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e) {
error(this.getClass(), e, "Exception occurred while waiting for the
lookup child threads completion.");
}
finally {
threadPoolExecutor.shutdown();
}
}