0
    StopWatch sw = new StopWatch();
    sw.start();
    ExecutorService executor = Executors.newFixedThreadPool(MYTHREADS);

    for (int i = 0; i < MYTHREADS; i++) {
        Runnable worker = new SingleConnectionRunnable();
        executor.execute(worker);
    }

    sw.stop();
    System.out.println("total time"+sw.toString());
    sw.reset();
    sw.start();

    for (int i = 0; i < MYTHREADS; i++) {
        Runnable worker2 = new PooledConnectionRunnable();
        executor.execute(worker2);
    }
    executor.shutdown();
    executor.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
    while (!executor.isTerminated()) {

    }

    sw.stop();
    System.out.println("total time"+sw.toString());

I am trying to run some perf tests on the code above. I am trying to use the same executor on different Runnable and measure the time. But it doesn't quite work. the first "total time" is not correct which is in milliseconds.

I want to print the elapsed time on the first loop then print the second loop. Not sure how I can wait executor to finish the first one then restart the executor.

What is the correct way to get this done?

DarthVader
  • 52,984
  • 76
  • 209
  • 300
  • 1
    Possible duplicate of [ExecutorService, how to wait for all tasks to finish](http://stackoverflow.com/questions/3269445/executorservice-how-to-wait-for-all-tasks-to-finish) – AxelH Feb 06 '17 at 13:41

2 Answers2

1

First, awaitTermination will block until all tasks terminate. Is there any particular reason that you use a while loop check after waiting potentially 70 years?

Anyways, to answer your question, in order to wait for the first run to finish, you should use a CountDownLatch to signal completion of each thread and await for them in the main thread until they finish. You can also use a CyclicBarrier to await until all your threads are ready to go before starting timing, like so:

...
CountDownLatch latch = new CountDownLatch(MYTHREADS);
CyclicBarrier cb = new CyclicBarrier(MYTHREADS, new Runnable() {
    @Override public void run() {
        sw.start();
    }
});

for (...) {
    Runnable worker = ...
    executor.execute(new Runnable() {
        @Override public void run() {
            try { 
                cb.await(); 
            } catch (Exception e) { 
                throw new RuntimeException(e); 
            }

            worker.run();
            latch.countDown();
        }
    });
}

latch.await();
sw.stop();
...

I moved the sw.start() to the beginning of the for-loop to avoid measuring object allocation overhead to setup (probably won't be measured anyways since its in ms).

You can also reset the two concurrency classes to run an indefinite number of times.

  • 1
    As I side note, if the OP still fears that `awaitTermination` could return without the executor service being completed within 68 years, after changing the call to `awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)`, it will wait until the end of the universe or, in other words, even `while (!executor.isTerminated()) {}` could spuriously terminate, due to a hardware failure within the 25269512429739111 years. Besides that, a `CountDownLatch` might be overkill, given that each `ExecutorService` provides `invokeAll`, which returns when all jobs are completed. Though, you have to use `Callable`… – Holger Feb 07 '17 at 09:50
  • @Holger I thought it would complicate the code further to have to provide a list although if OP uses a Callable already then I think it would be worth using `invokeAll`... –  Feb 07 '17 at 13:36
0

What you are doing now is:

  1. Start the stopwatch
  2. Start a few threads
  3. Read the stopwatch

You are not waiting for them to finish like you do with the second loop.


This is what you can do to fix this.

Make a callback method in the SingleConnectionRunnable.

This method will be called at the last point of this runnable (when you terminate it) and caught by the class that starts the loop (which is not method in the question but that is fine).

In this callback method you keep track of how many times it is called.

When it is called MYTHREAD amount of times you print the stopwatch time.

Now you know how long it will take until all started threads are finished.

Totumus Maximus
  • 7,543
  • 6
  • 45
  • 69