Java - 将工作分割为多个线程 [英] Java - splitting work to multiple threads

查看:130
本文介绍了Java - 将工作分割为多个线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我提出了以下问题:出于性能原因,我需要在多个线程之间拆分工作,但我不确定采取什么方法。

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.

首先,我将提供的任务应该返回一个值并获取一个参数。此外,主要方法(执行主要工作,而不是 static main())已经在单独的线程上运行并定期调用。此外,此方法必须在某个时刻等待所有线程完成然后继续。

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
}

这有点难看,不太理想,因为正如我所说,mainMethod被多次调用,我不希望在设置结果变量时有任何竞争条件。理想情况下,我想让它们成为局部变量,但是我不能在run方法中访问它们,除非它们是final,然后我不能为它们赋值......

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...

我做的另一种方法是:

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
}

这会自动等待main方法的这两个计算,并允许我在本地存储结果。你觉得怎么样?任何其他方法?

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?

推荐答案

使用 ExecutorService 的方法几乎就是最现代,最安全的方式来做到这一点。建议将 Callable 提取到单独的类中:

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();

一些注释:


  • 如果您只想同时处理两个任务,那么16个线程太多了 - 或者您想从多个客户端线程重用该池?

  • 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?

记得关闭游泳池

使用轻量级 ExecutorCompletionService 等待完成的第一个任务,不一定是第一个提交。

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

如果您需要完全不同的设计理念,请查看 akka 及其基于actor的并发模型。

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

这篇关于Java - 将工作分割为多个线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆