dinesh mahadasyam
dinesh mahadasyam

Reputation: 33

calling different methods of same class using multi threading in java

I have a class as below with three methods

public class MyRunnable implements Runnable {

    @Override
    public void run() {
        // what code need to write here 
        //to call the specific methods based on request types
    }

    public int add(int a, int b){
        return a+b;
    }

    public int multiply(int a , int b){
        return a*b;
    }

    public int division(int a , int b){
        return a/b;
    }

}

and my main class as blow here r.multiply(), add() and division() methods will be executed sequentially, but i want to execute them in multi-threaded way hence i can get the result faster. how to call a method of a class dynamically based on inputs. how to pass to thread and how to return result from thread to calling thread.

public class ThreadDemo {

    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();

        // how to do below calculation using multihtreading
        // how to call a method and how to get result of a thread of same class
        int result = r.multiply(1, 2) + r.add(4, 5) + r.division(10, 5);
        System.out.println(result);

        int newResult = r.add(20, 50);
        System.out.println(newResult);
    }
}

Upvotes: 3

Views: 2772

Answers (1)

John McClean
John McClean

Reputation: 5313

Multi-threading would slow down this application (because the amount of processing per step is far to small to justify the overhead of distributing the work across threads), the application probably finishes well before you perceive it anyway.

Assuming it's a simplified example you can write

 MyRunnable r = new MyRunnable();
 Executor exec = Executors.newFixedThreadPool(3);

 CompletableFuture<Integer> mult = CompletableFuture.runAsync(() -> r.multiply(1, 2),exec );
 CompletableFuture<Integer> add = CompletableFuture.runAsync(() -> r.add(4, 5) ,exec);
 CompletableFuture<Integer> div = CompletableFuture.runAsync(() -> r.division(10, 5),exec);

 CompletableFuture<Integer> result = mult.thenCombine(add, (multRes,addRes) -> multRes+addRest)
                                         .thenCombine(div, (total,divRes) -> total+divRes);

 int answer = result.join();

UPDATE Why use an explicitly defined Executor?

  • It shows readers how to explicitly define an executor (the alternative is straightforward)

  • By defining the Executor as a variable, you can switch between the Common ForkJoinPool (or any other executor type) by changing just that variable assignment (you don't have to refactor all of the methods). E.g.

    //ForkJoinPool common
    Executor exec = ForkJoinPool.commonPool();
    
    //Expanding thread pool
    Executor exec = Executors.newCachedThreadPool();
    
    //Just execute on the current thread
    Executor exec = (Runnable r)  -> r.run();
    
  • By default CompletableFuture.*Async methods share the Common ForkJoinPool and so do Parallel Streams, along with ForkJoinTasks without a specific executor. Unless all members of the team think carefully about when to / not to use the Common ForkJoinPool you could end up mixing async I/O operations with CPU bound processing in the same pool accidentally.

  • Also by default, the parallelism is set to Runtime.getRuntime().availableProcessors() - 1. Which again, may or may not suit the use case at hand (for some users it might mean this example was single threaded). It is configurable via the System Property "java.util.concurrent.ForkJoinPool.common.parallelism", if you need to change the defaults.

Upvotes: 5

Related Questions