1

我正在用 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;
  }
}
4

1 回答 1

0

我的猜测是正在进行大量的上下文切换。我的建议是将 ExecutorService 从方法变量转移到服务(或控制器)类中的字段。

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();
    }
}
于 2017-04-06T01:41:51.470 回答