Search code examples
javamultithreadingconcurrencyjava.util.concurrentcallable

why increment of newFixedThreadPool result in poor performance?


I'm trying to change the execution of a report and have it done in concurrency. In a 'serail mode' the execution test takes 30 seconds and when using a concurrent mode I get 27 seconds (consider that few steps must be taken in serial I'm ok with the result).

The thing that I still don't get is this line:

ExecutorService executor = Executors.newFixedThreadPool(4);

My computer is armed with 2x2.6 Ghz Quad Core and I would expect that the execution time will decrease if the newFixedThreadPool is high (16). In reality, the more I increase the newFixedThreadPool the slower the execution. This begs the question: What am I doing wrong or what am I failing to understand?!?!

I'm embedding 2 results screenshots from my execution.

A. newSingleThreadExecuter - runs in 23 sec

B. newFixedThreadPool(4) - runs in 43 sec.

Each time I submit a 'Worker' I get system.out the currentTimeMillis and the "fatched tkt" result is milliseconds that it takes to get the data from the db. (in strategy A - it takes ~3ms and in B up to 7ms).

    Stopper stopper = new Stopper();
    for (Long iNum : multimap.asMap().keySet())
    {
        List<Long> tickets = (List<Long>) multimap.get(iNum);
        for (Long ticketNumber : tickets)
        {
                pojoPks = getPkData(iNum);
                Callable<PojoTicket> worker = new MaxCommThread(ticketNumber, pojoPks);
                Future<PojoTicket> submit = executor.submit(worker);
                futures.add(submit);
        }
    }

    System.out.println("futurues: " +futures.size());
    for (Future<PojoTicket> future : futures)
    {
        try
        {
            PojoTicket pojoTicket = future.get();
            //do the rest here

        } catch (InterruptedException e)
        {
            System.out.println("---------------------->InterruptedException");
        } catch (ExecutionException e)
        {
            System.out.println("---------------------->ExecutionException");
        }
    }

    executor.shutdown();
    stopper.stop();

enter image description here

enter image description here


Solution

  • the more I increase the newFixedThreadPool the slower the execution

    In general, if you add threads to a job and it doesn't speed it up it could be because of one of a couple of reasons:

    • Each of the jobs have to synchronize on some sort of resource so they are all fighting for lock contention and not running independently.

    • The jobs do not have much CPU work to be done. Adding threads to an IO bound process will not make things go faster because the IO channel may already be maxed out.

    However, it is an interesting situation if you your application runs half as fast. I can only guess that it is a combination of the two of them.

    One thing to try is to start with 1 thread and then try 2. If it doesn't run faster then first take a look at what locks are shared between the jobs. What concurrent collections or other objects are being modified by each job? Try to reduce the number of locks or have the threads store temporary information and then lock once to update the central objects.

    You can also watch your system statistics to see if your IO channels are maxed out. Disk a common issue here. See if you can run on a memory disk to see if your application runs faster. That will be an indicator that you are IO bound.

    Lastly, I would look into why you are getting any ExecutionExceptions when you jobs get reaped. This may be an indicator of some other problem but you should understand this first.