Search code examples
javaconcurrencyjava.util.concurrent

How to Measure execution time for a multi threaded task in java


I have a method which makes lets say 100k http calls to an API, for that reason I am making the http calls concurrently to avoid http bottleneck. But I would also like to time the whole method without blocking any threads.

        ExecutorService service = Executors.newFixedThreadPool(500);
        for (int i = 0; i < 100_000; i++) {
            int finalI = i;
            Runnable runnable = () -> {
                // My http call goes here....
            };
            service.submit(runnable);
        }

Solution

  • If you wish to get a rough idea of the time the whole set of operations takes then use shutdown then awaitTermination to wait for the executor service to finish all of the submitted tasks. Here is a simple example:

    long start= System.nanoTime();
    ExecutorService exec = Executors.newFixedThreadPool(100);
    try {
        for (int i = 0; i < 100_000; i++) {
            final int x = i;
            Runnable runnable = () -> System.out.println(x);
            exec.submit(runnable);
        }
    } finally {
        exec.shutdown();
        exec.awaitTermination(365, TimeUnit.DAYS);
    }
    long elapsed = System.nanoTime() - start;
    System.out.println("Elapsed millisec "+TimeUnit.NANOSECONDS.toMillis(elapsed));
    

    It's not a good idea to put System.out.println or other logging inside the tasks as then you are only timing your console I/O, and not getting an estimate of how quick your processing is.

    As in the comments, using multi-thread access to same set of servers / resource / disk can make overall elapsed time get longer or cause issues elsewhere.

    From JDK19 the ExecutorService is AutoCloseable so you can simplify the try block and remove the finally:

    try (ExecutorService exec = Executors.newFixedThreadPool(100)) {
         ...
    }