How to configure the following thread in Java?

I have a stream with the following form:

  • each execution of each thread should run a function in the class. This feature is completely safe to run on its own. The function returns a value, for example, int.

  • After all the threads are completed, the values ​​of the functions must be accumulated.

So it goes (in pseudo-code) something like this:

a = 0 for each i between 1 to N spawn a thread independently and call the command v = f(i) when thread finishes, do safely: a = a + v end 

I am not sure how to use Java in this case.

The problem is not creating the stream, I know that this can be done with

 new Thread() { public void run() { ... } } 

The problem accumulates all the answers.

Thanks for any info.

+4
source share
2 answers

I would probably do something like:

  public class Main { int a = 0; int[] values; int[] results; public Main() { // Init values array results = new int[N]; } public int doStuff() { LinkedList<Thread> threads = new LinkedList<Thread>(); for (final int i : values) { Thread t = new Thread() { public void run() { accumulate(foo(i)); } }; threads.add(t); t.start(); } for (Thread t : threads) { try { t.join(); } catch (InterruptedException e) { // Act accordingly, maybe ignore? } } return a; } synchronized void accumulate(int v) { // Synchronized because a += v is actually // tmp = a + v; // a = tmp; // which can cause a race condition AFAIK a += v; } } 
+4
source

Use ExecutorCompletionService , Executor and Callable .:

Start with Callable , which calls your int function:

 public class MyCallable implements Callable<Integer> { private final int i; public MyCallable(int i) { this.i = i; } public Integer call() { return Integer.valueOf(myFunction(i)); } } 

Create an Executor :

 private final Executor executor = Executors.newFixedThreadPool(10); 

10 - the maximum number of threads to execute immediately.

Then wrap it in an ExecutorCompletionService and submit your jobs:

 CompletionService<Integer> compService = new ExecutionCompletionService<Integer>(executor); // Make sure to track the number of jobs you submit int jobCount; for (int i = 0; i < n; i++) { compService.submit(new MyCallable(i)); jobCount++; } // Get the results int a = 0; for (int i = 0; i < jobCount; i++) { a += compService.take().get().intValue(); } 

ExecutorCompletionService allows you to pull jobs out of the queue as they are completed. This is slightly different from thread pooling. Although the overall result is the same, if you want to update the user interface as threads finish, you won’t know in which order the threads will be terminated using the connection. This last for loop could be like this:

 for (int i = 0; i < jobCount; i++) { a += compService.take().get().intValue(); updateUi(a); } 

And this will update the user interface when tasks are completed. Using Thread.join will not necessarily do this, as you will get the results in the order in which you call the connections, and not in the order in which the threads terminated.

Using an artist, this will also allow you to limit the number of simultaneous tasks that you are currently performing so that you do not accidentally bomb your system.

+3
source

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


All Articles