我正在用 Java 7 编写一个 REST API 来从数据库中检索三个项目并将所有三个项目作为响应一起发送给用户。当程序在顺序流中运行时,即如果我获取一个项目然后另一个项目,那么它需要合法的时间来执行。但是当我使用多线程,即使用三个线程从数据库中获取三个项目时,与顺序相比,它需要更多的执行时间。这个问题导致CPU 使用率 超过 90%。
例子:
Sequential: number of users 60
average execution time- 5149 milliseconds
Parallel: number of users 60
average execution time- 9544 milliseconds
我正在使用 ExecutorService 来实现异步执行机制和用于线程同步的Countdown 锁存器。
为什么并行执行比顺序执行花费更多时间?在这里使用倒计时锁存器有什么缺点吗?
使用倒计时闩锁执行工作线程的代码:
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();
}
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;
}
}