我有一些练习,其中一个是关于并发的。这个主题对我来说是新的,但是我花了 6 个小时终于解决了我的问题。但是我对相应API的了解很差,所以我需要建议:我的解决方案是正确的还是可能有更合适的方法。
所以,我必须实现下一个接口:
public interface PerformanceTester {
/**
* Runs a performance test of the given task.
* @param task which task to do performance tests on
* @param executionCount how many times the task should be executed in total
* @param threadPoolSize how many threads to use
*/
public PerformanceTestResult runPerformanceTest(
Runnable task,
int executionCount,
int threadPoolSize) throws InterruptedException;
}
其中PerformanceTestResult包含总时间(整个性能测试总共花费了多长时间)、最短时间(最短的单次执行花费了多长时间)和最长时间(最长的单次执行花费了多长时间)。
所以,我今天学到了很多新东西——关于线程池、类型Executors、、等等。ExecutorServiceFutureCompletionService
如果我有 Callable task,我可以做下一个:
- 在程序结束时返回当前时间
call()。 - 创建一些数据结构(可能是一些 Map)来存储开始时间和
Future对象,由fixedThreadPool.submit(task)(执行此executionCount时间,循环)重新调整; - 执行后,我可以从结束时间中减去开始时间
Future。
(在Callable 任务的情况下这是正确的方法吗?)
但!我只有Runnable task,所以我继续寻找。我什至创建FutureListener implements Callable<Long>,必须返回时间,何时Future.isDone(),但对我来说接缝有点疯狂(我必须加倍线程数)。
因此,最终我注意到CompletionServicetype 带有有趣的方法take(),它检索并删除代表下一个已完成任务的 Future,如果还没有则等待。,以及使用ExecutorCompletionService的非常好的示例。还有我的解决方案。
public class PerformanceTesterImpl implements PerformanceTester {
@Override
public PerformanceTestResult runPerformanceTest(Runnable task,
int executionCount, int threadPoolSize) throws InterruptedException {
long totalTime = 0;
long[] times = new long[executionCount];
ExecutorService pool = Executors.newFixedThreadPool(threadPoolSize);
//create list of executionCount tasks
ArrayList<Runnable> solvers = new ArrayList<Runnable>();
for (int i = 0; i < executionCount; i++) {
solvers.add(task);
}
CompletionService<Long> ecs = new ExecutorCompletionService<Long>(pool);
//submit tasks and save time of execution start
for (Runnable s : solvers)
ecs.submit(s, System.currentTimeMillis());
//take Futures one by one in order of completing
for (int i = 0; i < executionCount; ++i) {
long r = 0;
try {
//this is saved time of execution start
r = ecs.take().get();
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
//put into array difference between current time and start time
times[i] = System.currentTimeMillis() - r;
//calculate sum in array
totalTime += times[i];
}
pool.shutdown();
//sort array to define min and max
Arrays.sort(times);
PerformanceTestResult performanceTestResult = new PerformanceTestResult(
totalTime, times[0], times[executionCount - 1]);
return performanceTestResult;
}
}
那么,你能说什么呢?感谢您的回复。