Alex Rivera | Logout

Java - splitting work to multiple threads

Asked 2012-10-11T18:07:51.297
13

I am posed with the following problem: I need to split work across multiple threads for perfomance reasons, but I am not sure what approach to take.

Firstly, the task I would be supplying should return a value and take a parameter. Additionally, the main method (doing the main bit of work, not static main() ) is already running on separate thread and is invoked periodically. Also, this method must at some point WAIT for all threads to finish and then proceed.

One approach (most obvious to me) is to schedule each job on a separate thread and store results in class vars:

public Object result1, result2;

public void mainMethod() throws InterruptedException {
    final Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            result1 = expensiveMethod("param1");
        }
    });

    final Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            result2 = expensiveMethod("param2");
        }
    });

    thread1.join();
    thread.join();

    //Do rest of work
}

private Object expensiveMethod(Object param){
    // Do work and return result
}

This is a bit ugly and not ideal, since as I said, mainMethod is invoked many times, and I do not want any race conditions on setting the result variables. Ideally, I would like to make them local variables, but I cannot make them accessible from within the run method, unless they are final, and then I cannot assign values to them...

Another approach I though about doing was this:

public void mainMethod() throws InterruptedException, ExecutionException {
    String obj1, obj2;

    final ExecutorService executorService = Executors.newFixedThreadPool(16);
    final Future<String> res1 = executorService.submit(new Callable<String>() {
        @Override
        public String call() throws Exception {
            return expensiveMethod("param1")
Edit
Report

2 Answers

2

Slightly different approach is:

  • create a LinkedBlockingQueue

  • pass it to each task. Tasks can be Threads, or Runnables upon j.u.c.Executor.

  • each task adds its result to the queue

  • the main thread reads results using queue.take() in a loop

This way results are handled as soon as they are computed.

answered 2012-10-11T18:39:57.473
2

You want to use the CompletionService and keep track of the submitted tasks.
In your loop you then take() and exit the loop when you've got all you tasks completed.
Scale very well is you add more tasks later.

answered 2012-10-12T17:28:38.007

Your Answer