1

So the thing is I have an object that does a computationally intensive task.

Assume the main class had two of these objects, I parallelized the process as following.

Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                    obj1.compute();
            }
        });
Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                    obj2.compute();
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();

But if I have an arbitrary number of objects, stored in a list, what would be the best way of doing that? (assume numbers in the magnitude of 10). I was looking into the executor service but could not figure how to rejoin the threads. The ForkJoinPool is supposed to do that, but I could not find how to make it work.

My priority is simple, clear code, rather than performance (since any overhead goes unseen in the 10min the computation takes).

3 Answers 3

4

You can simply try to call get on the returned futures, which will block until the tasks complete. For example:

ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future> futures = new ArrayList<> ();

for (Runnable r : yourListOfRunnables) {
    futures.add(executor.submit(r));
}

//now do the equivalent of join:

try {
    for (Future f : futures) {
        f.get(); //blocks until the runnable completes
    }
} catch (...) { }

Note: don't forget to shutdown the executor when you are done or it might prevent your application from exiting.

Alternatively, if this is a one-off thing, you can shutdown the executor and wait until it is terminated:

ExecutorService executor = Executors.newFixedThreadPool(10);

for (Runnable r : yourListOfRunnables) {
    executor.submit(r);
}

executor.shutdown(); //do not accept more tasks
executor.awaitTermination(Long.MAX_VALUE, SECONDS); //waits until all tasks complete

//at this point: all tasks have completed and 
//your executor is terminated: you can't reuse it
Sign up to request clarification or add additional context in comments.

1 Comment

You feel the love don't you?
1

Another way, still using java.util.concurrent:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ForkJoin {
   static final int THREAD_COUNT = 10;
   public static void main( String[] args ) throws InterruptedException {
      ExecutorService executor = Executors.newFixedThreadPool( THREAD_COUNT );
      final CountDownLatch cdl = new CountDownLatch( THREAD_COUNT );
      for( int i = 0; i < THREAD_COUNT; ++i ) {
         executor.execute( new Runnable(){
            @Override public void run(){
               try {
                  Thread.sleep((long)( 2000.0 + 1000.0*Math.random()));
                  System.err.println( "Done." );
                  cdl.countDown();
               }
               catch( InterruptedException e ) {
                  e.printStackTrace();
               }
            }});
      }
      cdl.await( 1, TimeUnit.DAYS );
      executor.shutdownNow();
      System.err.println( "All done." );
   }
}

Outputs:

Done.
Done.
Done.
Done.
Done.
Done.
Done.
Done.
Done.
Done.
All done.

Comments

0

Take a look at this tutorial: Java Thread Pool Example using Executors and ThreadPoolExecutor and the docs on ExecutorService. If you make a number of runnable tasks, as you do above, and then add them to a list you should be able to feed them all at once to your executor and get them all back in one collection too:

    tasks = new HashSet<Runnable>();
    for (int i = 0; i < 10; i++) {
        Runnable worker = new WorkerThread('' + i);
        tasks.add(worker);
      }

    //start processing and get a list of all the futures
    List<Future> futures = executor.invokeAll(tasks);
    for (Future f: futures) {
       f.get();
    }

The first future in the list may not be the one first Future done, but the delay of getting the value should't slow things down too much.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.