我有一些练习,其中一个是关于并发的。这个主题对我来说是新的,但是我花了 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
、、等等。ExecutorService
Future
CompletionService
如果我有 Callable task
,我可以做下一个:
- 在程序结束时返回当前时间
call()
。 - 创建一些数据结构(可能是一些 Map)来存储开始时间和
Future
对象,由fixedThreadPool.submit(task)
(执行此executionCount
时间,循环)重新调整; - 执行后,我可以从结束时间中减去开始时间
Future
。
(在Callable 任务的情况下这是正确的方法吗?)
但!我只有Runnable task
,所以我继续寻找。我什至创建FutureListener implements Callable<Long>
,必须返回时间,何时Future.isDone()
,但对我来说接缝有点疯狂(我必须加倍线程数)。
因此,最终我注意到CompletionService
type 带有有趣的方法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;
}
}
那么,你能说什么呢?感谢您的回复。