3

I have the code like the below. In a loop it is executing the method "process". It is running sequentially. I want to run this method parallel, but it should be finished within the loop so that I can sum in the next line. i.e even it is running parallel all functions should finish before the 2nd for loop execute.

How to solve this in Jdk1.7 not JDK1.8 version?

public static void main(String s[]){
    int arrlen = 10;
    int arr[] = new int[arrlen] ;

    int t =0;
    for(int i=0;i<arrlen;i++){
        arr[i] = i;
        t = process(arr[i]);
        arr[i] = t;
    }

    int sum =0;
    for(int i=0;i<arrlen;i++){
        sum += arr[i];
    }
    System.out.println(sum);

}

public static int process(int arr){
    return arr*2;
}
2

2 Answers 2

3

Below example might help you. I have used fork/join framework to do that.

For small array size like your example, conventional method might be faster and I doubt that fork/join way would take slight higher time. But for larger size or process , fork/join framework is suitable. Even java 8 parallel streams uses fork/join framework as underlying base.

public class ForkMultiplier extends RecursiveAction {
        int[] array;
        int threshold = 3;
        int start;
        int end;

        public ForkMultiplier(int[] array,int start, int end) {
            this.array = array;
            this.start = start;
            this.end = end;
        }

        protected void compute() {
            if (end - start < threshold) {
                computeDirectly();
            } else {
                int middle = (end + start) / 2;
                ForkMultiplier f1= new ForkMultiplier(array, start, middle);
                ForkMultiplier f2= new ForkMultiplier(array, middle, end);
                invokeAll(f1, f2);
            }
        }

        protected void computeDirectly() {
            for (int i = start; i < end; i++) {
                array[i] = array[i] * 2;
            }
        }
    }

You main class would like this below

 public static void main(String s[]){

        int arrlen = 10;
        int arr[] = new int[arrlen] ;


        for(int i=0;i<arrlen;i++){
            arr[i] = i;
        }

        ForkJoinPool pool = new ForkJoinPool();
        pool.invoke(new ForkMultiplier(arr, 0, arr.length));

        int sum =0;
        for(int i=0;i<arrlen;i++){
            sum += arr[i];
        }

        System.out.println(sum);

    }
Sign up to request clarification or add additional context in comments.

Comments

0

You basically need to use Executors and Futures combined that exist since Java 1.5 (see Java Documentation).

In the following example, I've created a main class that uses another helper class that acts like the processor you want to parallelize.

The main class is splitted in 3 steps:

  1. Creates the processes pool and executes tasks in parallel.
  2. Waits for all tasks to finish their work.
  3. Collects the results from tasks.

For didactic reasons, I've put some logs and more important, I've put a random waiting time in each process' business logic, simulating a time-consuming algorithm ran by the Process class.

The maximum waiting time for each process is 2 seconds, which is also the highest waiting time for step 2, even if you increase the number of parallel tasks (just try changing the variable totalTasks of the following code to test it).

Here the Main class:

package com.example;

import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Main
{
    public static void main(String[] args) throws InterruptedException, ExecutionException
    {
        int totalTasks = 100;

        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(totalTasks);

        System.out.println("Step 1 - Starting parallel tasks");

        ArrayList<Future<Integer>> tasks = new ArrayList<Future<Integer>>();
        for (int i = 0; i < totalTasks; i++) {
            tasks.add(newFixedThreadPool.submit(new Process(i)));
        }

        long ts = System.currentTimeMillis();
        System.out.println("Step 2 - Wait for processes to finish...");

        boolean tasksCompleted;
        do {
            tasksCompleted = true;

            for (Future<Integer> task : tasks) {
                if (!task.isDone()) {
                    tasksCompleted = false;
                    Thread.sleep(10);
                    break;
                }
            }

        } while (!tasksCompleted);

        System.out.println(String.format("Step 2 - End in '%.3f' seconds", (System.currentTimeMillis() - ts) / 1000.0));

        System.out.println("Step 3 - All processes finished to run, let's collect results...");

        Integer sum = 0;

        for (Future<Integer> task : tasks) {
            sum += task.get();
        }

        System.out.println(String.format("Total final sum is: %d", sum));
    }
}

Here the Process class:

package com.example;

import java.util.concurrent.Callable;

public class Process implements Callable<Integer>
{
    private Integer value;

    public Process(Integer value)
    {
        this.value = value;
    }

    public Integer call() throws Exception
    {
        Long sleepTime = (long)(Math.random() * 2000);

        System.out.println(String.format("Starting process with value %d, sleep time %d", this.value, sleepTime));

        Thread.sleep(sleepTime);

        System.out.println(String.format("Stopping process with value %d", this.value));

        return value * 2;
    }
}

Hope this helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.