所花费的总时间和平均所用时间

时间:2013-03-16 20:52:57

标签: java multithreading average executorservice

我正在开展一个项目,我需要测量项目所花费的总时间和计划所用的平均时间。该程序是一个多线程程序。

在该程序中,每个线程都在特定范围内工作。输入参数为Number of ThreadsNumber of Task

如果number of threads is 2number of tasks is 10,则每个帖子都会执行10 tasks。这意味着2个线程将执行20 tasks

这意味着 -

第一个帖子应该使用1 and 10之间的ID,第二个帖子应该使用11 and 20之间的ID。

我让上述方案有效。现在我想测量所有线程的总时间和平均时间。所以我在我的程序中得到了以下设置。

问题陈述: -

在我的下面的程序中,有人能告诉我我试图通过所有线程测量Total time and Average time taken的方式是否正确?

//create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(noOfThreads);

long startTime = 0L;
try {

    readPropertyFiles();

    startTime = System.nanoTime();

    // queue some tasks
    for (int i = 0, nextId = startRange; i < noOfThreads; i++, nextId += noOfTasks) {

        service.submit(new XMPTask(nextId, noOfTasks, tableList));
    }

    service.shutdown();
    service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

} finally {
    long estimatedTime = System.nanoTime() - startTime;
    logTimingInfo(estimatedTime, noOfTasks, noOfThreads);
}



private static void logTimingInfo(long elapsedTime, int noOfTasks, int noOfThreads) {

    long timeInMilliseconds = elapsedTime / 1000000L;
    float avg = (float) (timeInMilliseconds) / noOfTasks * noOfThreads;

    LOG.info(CNAME + "::" + "Total Time taken " + timeInMilliseconds + " ms. And Total Average Time taken " + avg + " ms");
}

3 个答案:

答案 0 :(得分:0)

service.submit仅执行noOfThreads次。 XMPTask对象的创建次数相同。

答案 1 :(得分:0)

您衡量的时间不是消耗时间,而是已过去时间。

如果测试的程序(JVM)是​​计算机上唯一的程序,它可能相对准确,但在现实世界中,许多进程同时运行。

我已经通过在Windows上使用对操作系统的本机调用(我将在星期一在我的办公室完成此帖子)和Linux(/ proc)来完成这项工作。

答案 2 :(得分:0)

我认为你需要测量任务类本身的时间(XMPTask)。在该任务中,您应该能够提取正在执行它的线程的id并记录它。使用此方法将需要读取日志并对其进行一些计算。

另一种方法是随着时间的推移保持总计和​​平均值的运行。为此,您可以编写一个简单的类,该类传递给每个具有一些静态(每个jvm)变量的任务,以跟踪每个线程正在执行的操作。然后你可以在Threadpool外部有一个执行计算的线程。因此,如果你想每秒报告每个线程的平均cpu时间,这个计算线程可以休眠一秒钟,然后计算并记录所有平均时间,然后再睡一秒......

编辑:重新阅读要求后,您不需要后台线程,但不确定我们是否跟踪每个线程的平均时间或每个任务的平均时间。我假设每个线程的总时间和平均时间,并在下面的代码中充实了这个想法。它尚未经过测试或调试,但应该让您了解如何开始:

public class Runner
{
    public void startRunning()
    {
        // Create your thread pool
        ExecutorService service = Executors.newFixedThreadPool(noOfThreads);

        readPropertyFiles();

        MeasureTime measure = new MeasureTime();

        // queue some tasks
        for (int i = 0, nextId = startRange; i < noOfThreads; i++, nextId += noOfTasks) 
        {

            service.submit(new XMPTask(nextId, noOfTasks, tableList, measure));
        }

        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
        measure.printTotalsAndAverages();
    }
}

public class MeasureTime
{
    HashMap<Long, Long> threadIdToTotalCPUTimeNanos = new HashMap<Long, Long>();
    HashMap<Long, Long> threadIdToStartTimeMillis = new HashMap<Long, Long>();
    HashMap<Long, Long> threadIdToStartTimeNanos = new HashMap<Long, Long>();

    private void addThread(Long threadId)
    {
        threadIdToTotalCPUTimeNanos.put(threadId, 0L);
        threadIdToStartTimeMillis.put(threadId, 0L);
    }

    public void startTimeCount(Long threadId)
    {
        synchronized (threadIdToStartTimeNanos)
        {
            if (!threadIdToStartTimeNanos.containsKey(threadId))
            {
                addThread(threadId);
            }

            long nanos = System.nanoTime();
            threadIdToStartTimeNanos.put(threadId, nanos);
        }
    }

    public void endTimeCount(long threadId)
    {
        synchronized (threadIdToStartTimeNanos)
        {
            long endNanos = System.nanoTime();
            long startNanos = threadIdToStartTimeNanos.get(threadId);

            long nanos = threadIdToTotalCPUTimeNanos.get(threadId);
            nanos = nanos + (endNanos - startNanos);
            threadIdToTotalCPUTimeNanos.put(threadId, nanos);
        }
    }

    public void printTotalsAndAverages()
    {
        long totalForAllThreadsNanos = 0L;
        int numThreads = 0;
        long totalWallTimeMillis = 0;
        synchronized (threadIdToStartTimeNanos)
        {
            numThreads = threadIdToStartTimeMillis.size();
            for (Long threadId: threadIdToStartTimeNanos.keySet())
            {
                totalWallTimeMillis += System.currentTimeMillis() - threadIdToStartTimeMillis.get(threadId);
                long totalCPUTimeNanos = threadIdToTotalCPUTimeNanos.get(threadId);

                totalForAllThreadsNanos += totalCPUTimeNanos;
            }
        }

        long totalCPUMillis = (totalForAllThreadsNanos)/1000000;
        System.out.println("Total milli-seconds for all threads: " + totalCPUMillis);
        double averageMillis = totalCPUMillis/numThreads;
        System.out.println("Average milli-seconds for all threads: " + averageMillis);

        double averageCPUUtilisation = totalCPUMillis/totalWallTimeMillis;
        System.out.println("Average CPU utilisation for all threads: " + averageCPUUtilisation);
    }
}

public class XMPTask implements Callable<String>
{
    private final MeasureTime measure; 

    public XMPTask(// your parameters first
            MeasureTime measure)
    {
        // Save your things first

        this.measure = measure;
    }

    @Override
    public String call() throws Exception
    {
        measure.startTimeCount(Thread.currentThread().getId());

        try
        {
            // do whatever work here that burns some CPU.
        }
        finally
        {
            measure.endTimeCount(Thread.currentThread().getId());
        }

        return "Your return thing";
    }
}

写完这一切后,有一件事看起来有点奇怪,因为XMPTask似乎对任务列表了解得太多,我认为你应该为你拥有的每一项任务创建一个XMPTask,给它有足够的信息来完成这项工作,并在您创建它们时将它们提交给服务。