加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java – 将工作分解到多个线程

发布时间:2020-12-14 16:33:41 所属栏目:Java 来源:网络整理
导读:我遇到了以下问题:为了执行性能原因,我需要跨多个线程分割工作,但我不知道采取什么方法. 首先,我将提供的任务应该返回一个值并获取一个参数.另外,主要方法(做主工作,而不是静态main())已经在单独的线程上运行,并且被定期调用.此外,该方法必须在某个时间点等
我遇到了以下问题:为了执行性能原因,我需要跨多个线程分割工作,但我不知道采取什么方法.

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

一种方法(对我来说最明显的)是在单独的线程上安排每个作业,并将结果存储在类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,然后我无法为它们赋值.

其他方法我虽然在做是这样的:

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方法自动等待这两个计算,并允许我在本地存储结果.你们怎么想?任何其他方法?

解决方法

您使用ExecutorService的方法几乎是最现代和最安全的方法.只需提取您的Callable来分离课程:
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);
    }

}

这将使您的代码更清洁:

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个线程太多了,如果你只想同时处理两个任务 – 或者你想从多个客户端线程重用该池?
记得关闭游泳池
>使用轻量级ExecutorCompletionService等待完成的第一个任务,不一定是提交的第一个任务.

如果您需要完全不同的设计思想,请查看akka及其基于actor的并发模型).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读