How to complete this paralell task in Java8

I am new to Java concurrency, so I am asking what is the best way to do these things:

I have a static method that matches the helper image inside the image. It looks like this:

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

The method returns null if nothing is matched, otherwise it returns a Match Point.

Now I have 40 different helper images for one (large) image, which I want to combine in parallel. Every second I get a new (large) image in which I need to search again and again for these 40 smaller images. I need the return values ​​of each call to match the method at the end of the match task in my main task, so I can analyze it. In addition, for this task I need to use as many processor cores as possible.

How can i do this? I read a lot about ExecutorService, Task, Runnable, etc. Most examples show how to print something on the console in parallel. I am really confused how I should go according to my scenario: how to convey values ​​and how to get results? What should the layout of the class (s) look like? Also, I have no idea how to go if I create 40 tasks per second (it will take some time to configure the task, right?)

The code would be very helpful to explain this :)

+5
source share
4 answers

Use a CompletionService , rather, a 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; } } 

If you want to use the entire processor, you probably want to change the ExecutorService to Executors.newWorkStealingPool() . Be careful with that though!

+4
source

I know that the answer has already been accepted, but I wanted to post a more “threaded” approach to this using java-8 threads. The code is much smaller, but it should work fine.

 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 } 
+2
source

It seems you are looking for a tutorial like this

0
source

You can use ExecutorService executorService = Executors.newFixedThreadPool(40); which will create a thread pool of 40 threads. Then create a class instance, for example CompareImage extends Callable , and then create 40 CompareImage objects, add to Collection . and then call the invokeAll() object on the executorService .

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

Source: https://habr.com/ru/post/1266464/


All Articles