Java 如何使用多线程测试任务性能?
我有一些练习,其中一个涉及并发性。这个主题对我来说是新的,但是我花了6个小时终于解决了我的问题。但我对相应的API的了解很差,所以我需要建议:我的解决方案是正确的还是有更合适的方法 因此,我必须实现下一个接口:Java 如何使用多线程测试任务性能?,java,multithreading,performance,concurrency,java.util.concurrent,Java,Multithreading,Performance,Concurrency,Java.util.concurrent,我有一些练习,其中一个涉及并发性。这个主题对我来说是新的,但是我花了6个小时终于解决了我的问题。但我对相应的API的了解很差,所以我需要建议:我的解决方案是正确的还是有更合适的方法 因此,我必须实现下一个接口: public interface PerformanceTester { /** * Runs a performance test of the given task. * @param task which task to do performan
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包含总时间(整个性能测试的总时间)、最短时间(最短单次执行的时间)和最长时间(最长单次执行的时间)
所以,今天我学到了很多新东西-关于线程池、类型执行器
、执行服务
、未来
、完成服务
等等
如果我有可调用任务
,我可以执行下一步:
call()过程的末尾返回当前时间
Future
对象,这些对象由fixedThreadPool.submit(task)
返回(在循环中执行此操作executionCount
次)李>
将来的结束时间中减去开始时间
可运行任务
,所以我继续寻找。我甚至创建了FutureListener实现可调用的,当Future.isDone()
时,它必须返回时间,但对我来说有点疯狂(我必须加倍线程计数)
因此,最终我注意到CompletionService
使用有趣的方法take()
键入,该方法检索并删除表示下一个已完成任务的未来,如果还没有,则等待,这是一个很好的使用示例。这就是我的解决方案
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;
}
}
公共类PerformanceTesterImpl实现PerformanceTester{
@凌驾
公共性能测试结果runPerformanceTest(可运行任务,
int executionCount,int threadPoolSize)引发InterruptedException{
长总时间=0;
long[]次=新的long[executionCount];
ExecutorService池=Executors.newFixedThreadPool(threadPoolSize);
//创建executionCount任务列表
ArrayList解算器=新的ArrayList();
for(int i=0;i
那么,你能说什么?感谢您的回复。我会使用System.nanoTime()进行更高分辨率的计时。您可能希望忽略前10000个测试,以确保JVM已经预热
我不会费心创建一个Runnable列表并将其添加到Executor。相反,我会将它们添加到遗嘱执行人中
使用Runnable并不是问题,因为您得到了一个Future
注意:计时任务在队列中花费的时间会对计时产生很大影响。不必从创建任务时开始计算时间,您可以将任务时间本身计算在内,并以纳秒为单位返回Long。时间安排的方式应该反映您心目中的用例
一种将可运行任务转换为自身计时任务的简单方法
finla Runnable run = ...
ecs.submit(new Callable<Long>() {
public Long call() {
long start = System.nanoTime();
run.run();
return System.nanoTime() - start;
}
});
finla可运行运行=。。。
ecs.submit(新的可调用(){
公共长途电话(){
长启动=System.nanoTime();
run.run();
返回系统.nanoTime()-开始;
}
});
我会使用System.nanoTime()进行更高分辨率的计时。您可能希望忽略前10000个测试,以确保JVM已经预热
我不会费心创建一个Runnable列表并将其添加到Executor。相反,我会将它们添加到遗嘱执行人中
使用Runnable并不是问题,因为您得到了一个Future
注意:计时任务在队列中花费的时间会对计时产生很大影响。不必从创建任务时开始计算时间,您可以将任务时间本身计算在内,并以纳秒为单位返回Long。时间安排的方式应该反映您心目中的用例
一种将可运行任务转换为自身计时任务的简单方法
finla Runnable run = ...
ecs.submit(new Callable<Long>() {
public Long call() {
long start = System.nanoTime();
run.run();
return System.nanoTime() - start;
}
});
finla可运行运行=。。。
ecs.submit(新的可调用(){
公共长途电话(){
长启动=System.nanoTime();
run.run();
返回系统.nanoTime()-开始;
}
});
在JVM中编写性能测试时有许多复杂的问题。您可能不担心他们,因为这是一个练习,但如果您担心,这个问题可能会有更多信息:
也就是说,您的代码中似乎没有任何明显的bug。如果您希望对代码进行全面审查,您可能需要在较低的交通代码审查网站上询问此问题:
在JVM中编写性能测试时有许多复杂的问题。您可能不担心他们,因为这是一个练习,但如果您担心,这个问题可能会有更多信息:
也就是说,似乎没有任何明显的bug