【问题标题】:How to execute multiple models in parallel instead of sequentially?如何并行执行多个模型而不是顺序执行?
【发布时间】:2015-01-18 06:56:11
【问题描述】:

我有各种模型,我正在依次执行这些模型。我将有大约 200 个模型。

下面是我的代码,我在其中一个一个地执行这些模型

Map<String, List<ServerMetrics>> metricsHolder = new HashMap<String, List<ServerMetrics>>();

for (String alias : serverNames) {
    List<ClientsModel> modelMetadata = getModelAttributes();
    List<MachineInfo> machineInfo = getMachineInfo();

    List<ServerMetrics> metricsList = new ArrayList<ServerMetrics>();

    // calling model one by one sequentially
    // is there any way to make this multithreaded?
    // here modelMetadata size might be 100 or 200
    for (ClientsModel modelList : modelMetadata) {
        String modelValue = modelList.getModelValue();
        String modelId = String.valueOf(modelList.getModelId());

        // execute my model here and storing the metrics in the metricsList object
        ServerMetrics metrics = TestUtils.executeModelMetrics(machineInfo, modelValue);
        metrics.setModelId(modelId);

        metricsList.add(metrics);
    }

    metricsHolder.put(alias, dynMetricsList);
}

问题陈述:-

有什么方法可以让模型执行多线程,然后将结果存储到metricsList 对象中?

【问题讨论】:

  • 如果执行不是相互依赖的,您可以为每个执行生成一个新线程,然后存储结果。不能吗?
  • 如果我有大约 200 个模型,那么你希望我生成 200 个线程吗?

标签: java multithreading thread-safety executorservice callable


【解决方案1】:

如果您的代码中没有数据竞争条件(多线程访问未正确同步的相同数据),那么您可以使用ExecutorService 形式的线程池来运行Callable线程上的实现。您可以在Callable 中完成工作。

在主线程上,ExecutorService 返回一个Future,然后您可以在所有任务都生成后等待。

线程池的大小(这里设置为10,但您可以更改它)决定了并行运行的数量。你仍然可以执行比线程池大小更多的Callables。

    Map<String, List<ServerMetrics>> metricsHolder = new HashMap<String, List<ServerMetrics>>();
    // Size of thread pool set at 10 - can be increased but increasing it 
    // to more than the number of cores on your computer is probably not 
    // useful, as it seems like your task is CPU-bound
    ExecutorService executorService = Executors.newFixedThreadPool(10);

    for (String alias : serverNames) {
        List<ClientsModel> modelMetadata = getModelAttributes();
        List<MachineInfo> machineInfo = getMachineInfo();

        List<Future<ServerMetrics>> metricsFutureList = new ArrayList<Future<ServerMetrics>>();

        // calling model one by one sequentially
        // is there any way to make this multithreaded?
        for (ClientsModel modelList : modelMetadata) {
            final String modelValue = modelList.getModelValue();
            final String modelId = String.valueOf(modelList.getModelId());

            metricsFutureList.add(executorService.submit(new Callable<ServerMetrics>() {
                @Override
                public ServerMetrics call() throws Exception {

                    // execute my model here and storing the metrics in the list
                    ServerMetrics metrics = TestUtils.executeModelMetrics(machineInfo, modelValue);
                    metrics.setModelId(modelId);
                    return metrics;
                }
            }));

        }
        List<ServerMetrics> metricsList = new ArrayList<ServerMetrics>();
        for (Future<ServerMetrics> future : metricsFutureList) {
            metricsList.add(future.get());
        }
        metricsHolder.put(alias, dynMetricsList);
    }

【讨论】:

  • 感谢您的好建议。在您的第一行中,您提到了一些关于 If there are no data race conditions 的内容,根据您的理解,什么可能导致我的代码出现问题?
  • 如果模型处理相同的数据(至少一个executeModelMetrics 方法更新至少另一个executeModelMetrics 读取的数据),那么您需要开始考虑多线程同步方法。如果executeModelMetrics 的多次调用在完全不同的Java 对象上工作,或者它们不修改Java 对象(如果值在线程启动之前已全部设置,则可以),那么您没有问题。跨度>
  • @ErwinBolwidt 是的,就我而言,executeModelMetrics 在不同的 Java 对象上工作,他们不会修改 Java 对象,所以应该没问题。
  • 但是他需要同步访问他的metricsHolderput() 在多个线程上存在损坏的危险。这使它安全:Map&lt;String, List&lt;ServerMetrics&gt;&gt; metricsHolder = Collections.synchronizedMap(new HashMap&lt;String, List&lt;ServerMetrics&gt;&gt;());
  • @gknicker 不是,因为metricsHolder 不能在多个线程中访问(仅在主线程中)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-05
  • 2020-09-08
  • 1970-01-01
  • 2017-03-25
  • 2018-06-25
  • 1970-01-01
相关资源
最近更新 更多