0
votes

I have been planning to use concurrency in project after learning it indeed has increased through put for many. Now I have not worked much on multi threading or concurrency so decided to learn and have a simple proof of concept before using it in actual project.
Below are the two examples I have tried:

1. With use of concurrency

    public static void main(String[] args) 

    {
        System.out.println("start main ");

        ExecutorService es = Executors.newFixedThreadPool(3);
        long startTime = new Date().getTime();
        Collection<SomeComputation> collection = new ArrayList<SomeComputation>();
        for(int i=0; i< 10000; i++){
            collection.add(new SomeComputation("SomeComputation"+i));
        }
        try {
            List<Future< Boolean >> list = es.invokeAll(collection);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\n end main "+(new Date().getTime() - startTime));
    }

2. Without use of concurrency

        public static void main(String[] args) {

          System.out.println("start main ");
          long startTime = new Date().getTime();
          Collection<SomeComputation> collection = new ArrayList<SomeComputation>();
          for(int i=0; i< 10000; i++){
          collection.add(new SomeComputation("SomeComputation"+i));
        }
        for(SomeComputation sc:collection)
        {
        sc.compute();
        }
        System.out.println("\n end main "+(new Date().getTime() - startTime));
        }

    Both share a common class

        class SomeComputation implements Callable<Boolean>
        {
            String name;
            SomeComputation(String name){this.name=name;}
            public Boolean compute()
            {
                someDumbStuff();
                return true;
            }

            public Boolean call()
            {
                someDumbStuff();
                return true;
            }

            private void someDumbStuff()
            {
                for (int i = 0;i<50000;i++)
                {
                    Integer.compare(i,i+1);
                }
                System.out.print("\n done with "+this.name);
            }
        }

Now the analysis after 20 odd runs of each approach.
1st one with concurrency takes on average 451 msecs.
2nd one without concurrency takes on average 290 msecs.
Now I learned this depends on configuration , OS , version(java 7) and processor. But all was same for both approaches. Also learned the cost of concurrency is affordable on when computation is heavy.But this point wasn't clear to me.
Hope some one can help me understand this more.
PS: I tried finding similar questions but could find this kind.Please comment the link if you do.

3
The late Gene Amdahl did some research you may find helpful; see also Amdahl's law.Elliott Frisch
Thanks @ElliottFrisch. I am going to read it right now.Viraj Nalawade
Try increasing the loop duration in someDumbStuff to about 1000000 and you may start to see a more expected trend.flakes
@flkes yes.. if I do that the approach with concurrency takes half the time compared to approach without concurrency.. this has something to learn.. thanks..Viraj Nalawade

3 Answers

2
votes

Concurrency has at least two different purposes: 1) performance, and 2) simplicity of code (like 1000 listeners for web requests).

If your purpose is performance, you can't get any more speedup than the number of hardware cores you put to work. (And that's only if the threads are CPU-bound.) What's more, each thread has a significant startup overhead. So if you launch 1000 threads on a 4-core machine, you can't possibly do any better than a 4x speedup, but against that, you have 1000 thread startup costs.

2
votes

As mentioned in one of answers, one use of concurrency is to have simplicity of code i.e. there are certain problems which are logically concurrent so there is no way to model those problems in a non-concurrent way like producer - consumer problems, listeners to web requests etc

Other than that, a concurrent program adds to performance only if its able to save CPU Cycles for you i.e. goal is to keep CPU or CPUs busy all the time and not waste its cycles, which further means that you let your CPU do something useful when your program is supposed to be busy in something NON - CPU tasks like waiting for Disk I/O, Wait for Locks , Sleeping, GUI app user wait etc - these times simply add time to your total program run time.

So the question is, what your CPU doing when your program not using it? Can I complete a portion of my program during that time and segregate waiting part in another thread? Now a days, most of modern systems are multiprocessor and multi core systems further leading to wastage if programs are not concurrent.

The example that you wrote is doing all the processing in memory without going into any of wait states so you don't see much gain but only loss in setting up of threads and context switching.

Try to measure performance by hitting a DB, get 1 million records, process those records and then save those records to DB again. Do it in one go sequentially and in small batches in concurrent way so you notice performance difference because DB operations are disk intensive and when you are reading or writing to DB, you are actually doing Disk I/O and CPU is free wasting its cycles during that time.

In my opinion, good candidates for concurrency are long running tasks involving one of wait operations mentioned above otherwise you don't see much gain.Programs which need some background tasks are also good candidates for concurrency.

Concurrency has not to be confused with multitasking of CPU i.e. when you run different programs on same CPU at the same time.

Hope it helps !!

1
votes

concurrecy is needed when the threads are sharing the same data sources so when some thread is working with this source the others must wait until it finish the job than they have the acces so you need to learn synchronized methode and bluck or some thing like that sorry for my english read this turial it's helpful https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html