当前位置: 首页 > 面试题库 >

在Java中并行化任务的最简单方法是什么?

施鸿
2023-03-14
问题内容

说我有一个类似的任务:

for(Object object: objects) {
    Result result = compute(object);
    list.add(result);
}

并行化每个compute()的最简单方法是什么(假设它们已经可以并行化了)?

我不需要严格匹配上面代码的答案,而只是一个常规答案。但是,如果您需要更多信息:我的任务是IO绑定的,这是针对Spring
Web应用程序的,这些任务将在HTTP请求中执行。


问题答案:

我建议看一下ExecutorService。

特别是这样的事情:

ExecutorService EXEC = Executors.newCachedThreadPool();
List<Callable<Result>> tasks = new ArrayList<Callable<Result>>();
for (final Object object: objects) {
    Callable<Result> c = new Callable<Result>() {
        @Override
        public Result call() throws Exception {
            return compute(object);
        }
    };
    tasks.add(c);
}
List<Future<Result>> results = EXEC.invokeAll(tasks);

请注意,newCachedThreadPool如果objects列表很大,使用可能会很糟糕。缓存的线程池可以为每个任务创建一个线程!您可能想newFixedThreadPool(n)在n合理的地方使用(例如,假设compute()CPU受限制,则具有的内核数)。

这是实际运行的完整代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorServiceExample {
    private static final Random PRNG = new Random();

    private static class Result {
        private final int wait;
        public Result(int code) {
            this.wait = code;
        }
    }

    public static Result compute(Object obj) throws InterruptedException {
        int wait = PRNG.nextInt(3000);
        Thread.sleep(wait);
        return new Result(wait);
    }

    public static void main(String[] args) throws InterruptedException,
        ExecutionException {
        List<Object> objects = new ArrayList<Object>();
        for (int i = 0; i < 100; i++) {
            objects.add(new Object());
        }

        List<Callable<Result>> tasks = new ArrayList<Callable<Result>>();
        for (final Object object : objects) {
            Callable<Result> c = new Callable<Result>() {
                @Override
                public Result call() throws Exception {
                    return compute(object);
                }
            };
            tasks.add(c);
        }

        ExecutorService exec = Executors.newCachedThreadPool();
        // some other exectuors you could try to see the different behaviours
        // ExecutorService exec = Executors.newFixedThreadPool(3);
        // ExecutorService exec = Executors.newSingleThreadExecutor();
        try {
            long start = System.currentTimeMillis();
            List<Future<Result>> results = exec.invokeAll(tasks);
            int sum = 0;
            for (Future<Result> fr : results) {
                sum += fr.get().wait;
                System.out.println(String.format("Task waited %d ms",
                    fr.get().wait));
            }
            long elapsed = System.currentTimeMillis() - start;
            System.out.println(String.format("Elapsed time: %d ms", elapsed));
            System.out.println(String.format("... but compute tasks waited for total of %d ms; speed-up of %.2fx", sum, sum / (elapsed * 1d)));
        } finally {
            exec.shutdown();
        }
    }
}


 类似资料:
  • 问题内容: 现在,我有一个Java程序,其类当前为POJO,并存储在易失性内存中。这些必须坚持下去。据我了解,两个流行的选择是JDO和Java Persistence API。对于对SQL,Torque等了解甚少的人,这是向程序数据添加持久性的最简单方法? 问题答案: 序列化到文件系统的传统方法是使用Java序列化。但是,您需要在各处实现Serializable。 一个更简单的解决方案是使用XSt

  • 最好的方法是什么?JCUDA是一个完美的映射到C CUDA还是完全不同?或者从Java调用C代码并共享结果是否有意义(链接列表是否可以访问)?

  • 问题内容: 在Java中,数组不会覆盖toString(),因此,如果您尝试直接打印一个数组,则得到数组的十六进制,如下所示: 但是通常情况下,我们实际上会想要更多类似的东西。最简单的方法是什么?以下是一些示例输入和输出: 问题答案: 从Java 5开始,您可以;然后将或用于数组中的数组。请注意,版本调用数组中的每个对象。输出甚至以您要求的确切方式修饰。 例子: 简单数组: 输出: 嵌套数组: 输

  • 问题内容: cgi.escape似乎是一种可能的选择。它运作良好吗?有什么更好的东西吗? 问题答案: 很好 它逃脱了: 至 至 至 对于所有HTML而言,这就足够了。 编辑:如果您有非ASCII字符,您还想转义,以便包含在使用不同编码的另一个编码文档中,如 Craig 所说,只需使用: 不要忘了解码到第一,使用任何编码它编码的。 但是根据我的经验,如果您从头开始一直都在工作,那么这种编码是没有用的

  • 问题内容: 我想在Java SE中拥有 我必须要做些什么?我在我的项目中使用postgres数据库和maven。 我已经在阅读有关Weld的内容(但看起来只像CDI)。我不知道如何增加焊接实体管理器的可能性。我知道我可以通过获得实体管理器 但它不如注射方便。 如果有关于它的任何教程,那就太好了。无论如何,谢谢您的帮助! 问题答案: 首先,EJB是Java EE的一部分,因此您不能在Java SE中

  • 我正在从我的应用程序中执行一个脚本,并通过Task value属性上的更改监听器用输出更新一个文本区域,但并不是所有行都显示出来。 我的问题基本上在JavaFX ChangeListener中得到了解决,并不总是有效,但我有一个后续问题。