【问题标题】:How to execute this paralell task in Java8如何在 Java 8 中执行此并行任务
【发布时间】:2017-04-07 10:00:02
【问题描述】:

我是 Java 并发方面的新手,所以我问什么是执行此类操作的最佳方式:

我有一个静态方法可以匹配图像中的子图像。看起来是这样的:

public static Point match(final BufferedImage subimage, final BufferedImage image)

如果没有匹配,该方法返回 null,否则返回匹配点。

现在我有一个(大)图像的 40 个不同的子图像,我想并行匹配。每秒钟我都会得到一个新的(大)图像,我需要在其中一遍又一遍地搜索这 40 个较小的图像。我需要在我的主任务中匹配任务结束时每次调用的返回值来匹配方法,所以我可以分析它。 此外,我需要为这项任务使用尽可能多的 CPU 内核。

我怎样才能做到这一点? 我已经阅读了很多关于 ExecutorService、Task、Runnable 等的内容。大多数示例仅显示如何在控制台上并行打印某些内容。我真的很困惑我应该在我的场景中走哪条路:如何传递值以及如何获得结果?类的布局应该如何?另外,如果我每秒创建 40 个任务,我也不知道该怎么办(设置任务需要一些时间,对吧?)

代码可以很好地解释它:)

【问题讨论】:

    标签: java multithreading concurrency java-8


    【解决方案1】:

    使用CompletionService,更可能是ExecutorCompletionService

    class Matcher {
      ExecutorService threadPool = Executors.newCachedThreadPool();
      private List<BufferedImage> subimages; // populate it yourself
      public static Point match(BufferedImage subimage, BufferedImage image) {
        // Your implementation
      }
      public List<Point> match(BufferedImage image) {
        CompletionService<Point> completionService = new ExecutorCompletionService(threadPool);
        int size = subimages.size();
        List<Point> results = new ArrayList<>(size);
        for (BufferedImage subimage: subimages) {
          completionService.submit(()->match(subimage, image));
        }
        for (int i = 0; i < size; i++) {
          Point point = completionService.take().get();
          if (point != null) {
            results.add(point);
          }
        }
        return results;
      }
    }
    

    如果您想使用所有 CPU,您可能需要将您的 ExecutorService 更改为 Executors.newWorkStealingPool()。不过要小心这个!

    【讨论】:

    • 哇,这正是我想要的!非常感谢:)
    【解决方案2】:

    我知道答案已经被接受,但我想使用 java-8 流发布一个更“流式”的方法。代码要小得多,但应该可以正常工作。

    for(BufferedImage bigImage:bigImages){
        List<Point> matchingPoints = subImages.parallelStream().map((smallImage) -> match(smallImage, bigImage)).collect(Collectors.toList());
        //do whatever you want to do with matchingPoints, like adding to a bigger list 
    }
    

    【讨论】:

      【解决方案3】:

      您似乎正在寻找类似this的教程

      【讨论】:

      • 这应该是一条评论
      • 然后进行那 50 次重复 :) 我实际上对此并不了解……但这仍然不适合作为答案,您可能会被否决。
      • 随意添加我的“答案”作为评论,我会删除它
      【解决方案4】:

      您可以使用ExecutorService executorService = Executors.newFixedThreadPool(40);,它将创建一个包含 40 个线程的线程池。然后创建像CompareImage extends Callable 这样的示例类,然后创建CompareImage 的40 个对象添加到Collection。 然后在executorService 对象上调用invokeAll()

      List<Future<Point>> list = executorService.invokeAll(listOfCompareImage);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-08
        • 1970-01-01
        • 2015-08-23
        • 2012-01-04
        相关资源
        最近更新 更多