Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
711 views
in Technique[技术] by (71.8m points)

multithreading - Java - splitting work to multiple threads

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");
        }
    });
    final Future<String> res2 = executorService.submit(new Callable<String>() {
        @Override
        public String call() throws Exception {
            return expensiveMethod("param2");
        }
    });

    obj1 = res1.get();
    obj2 = res2.get();

}

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

This automatically waits on these two computations from main method and allows me to store the results locally. What to you guys think? Any other approaches?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your approach with ExecutorService is pretty much the most modern and safe way to do this. It is recommended to extract your Callables to separate class:

public class ExpensiveTask implements Callable<String> {

    private final String param;

    public ExpensiveTask(String param) {
        this.param = param;
    }

    @Override
    public String call() throws Exception {
        return expensiveMethod(param);
    }

}

which will make your code much cleaner:

final ExecutorService executorService = Executors.newFixedThreadPool(16);
final Future<String> res1 = executorService.submit(new ExpensiveTask("param1"));
final Future<String> res2 = executorService.submit(new ExpensiveTask("param2"));
String obj1 = res1.get();
String obj2 = res2.get();

A few notes:

  • 16 threads are too much if you only want to process two tasks simultaneously - or maybe you want to reuse that pool from several client threads?

  • remember to close the pool

  • use lightweight ExecutorCompletionService to wait for the first task that finished, not necessarily for the first one that was submitted.

If you need a completely different design idea, check out with its actor based concurrency model.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...