Domanda

I am playing around with Java lacthes and wrote a piece of code to calculate some stuff in a parallel manner. The data, basically consists of a Map that each map has a list of numbers as value. My goal is to sum up all the values for all keys in this map. To start with, I thought it is a good idea to get the sum of all values for each key in a separate thread (each key has its own separate thread) and at the end I add up what is returned from each thread to get the total sum. I use a simple CounDownLatch in my code:

public static void main(String[] args) throws InterruptedException, ExecutionException
    {
        //final CountDownLatch startGate = new CountDownLatch(1);
        final CountDownLatch endGate = new CountDownLatch(3);


        Map> data =  new HashMap>();
        Set summedData = new HashSet();
        // populate the map with data
        populateMap(data);
        //separate the data with keys
        //send each list to a new thread to process

        for (String key : data.keySet())
        {
            final List list = data.get(key);
            System.out.println(list);

            //create a FutureTask
            FutureTask future = new FutureTask(new Callable()
            {

                @Override
                public Integer call() throws Exception
                {
                    int sum = new Mapx(list).getSum();
                    endGate.countDown();
                    return sum;
                }
            });

            Thread t = new Thread(future);
            t.start();
            System.out.println(t.getState());
            summedData.add(future.get());
        }
        //keep the main method on hold until all the thread do their job
        endGate.await();
        //send to reduce
        int total = new Reduce(summedData).addAll();
        System.out.println(total);

    }

My expectation is that, if the calculation of summing up all the items in a list for a key takes long, the thread running for this key, runs in the background and another thread for the next key starts to calculate. In other words, the calculations be done on in parallel. However, i see that this is not the case, and threads are run in serial. Can someone help me how I can achieve my goal and make this piece of code parallel?

È stato utile?

Soluzione

You call future.get() from within the loop. This method will block until the result is calculated, and therefore the loop will not continue until the other thread is done calculating, resulting in the serialized behavior you get.

To get the behavior you desire, you should have a loop launching all futureTasks on threads, and then a loop getting the results from all the FutureTasks using get().

You're also probably better off submitting a Callable to an ExecutorService (see Executors), and the ExecutorService will make the Future for you.

In fact launching calculations in parrallel and waiting for their results is what an ExectorService's invokeAll() method does for you.

The use of CountDownLatch is superfluous, as the Future objects already have the necessary synchronization behavior on board.

Altri suggerimenti

Just wanted to add one thing, this parallel processing would take less time only if your processor is at least dual core. If you have a single core processor then this approach could actually take more time

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top