calling different methods of same class using multi threading in java - 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);
}
}

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.

Related

How to thread a sequence of actions through multiple threads?

I am exploring a problem which is likely a special case of a problem class, but I don't know the problem class nor the appropriate terminology, so I have to resort to desribing the problem using ad-hoc vocabulary. I'll rephrase once I know the right terminology.
I have a bunch of singletons A, B, C. The singletons are:
Unrelated. There are no constraints like "you must access B before you can do X with C" or similar.
Not thread-safe.
The system accepts tasks to be processed in parallel as far as possible.
Each task consists of a sequence of actions, each action to be executed using one of the singletons. Different tasks may access different singleton in different order, and tasks may contain loops of actions.
Pseudocode:
void myTask(in1, in2, ...) {
doWithA(() -> {
// use in1, in2, ...
// inspect and/or update A
// set up outputs to be used as inputs for the next action:
outA1 = ...
outA2 = ...
...
});
doWithB(() -> {
// use outA1, outA2, ...
// inspect and/or update B
// set up outputs to be used as inputs for the next action:
outB1 = ...
outB2 = ...
...
});
// Tasks may touch singletons repeatedly, in any order
doWithA(() -> {
// outB1, outB2, ..., inspect/modify A, set up outputs
outAx1 = ...
outAx2 = ...
...
});
// Tasks may have loops:
while (conditionInC(() -> ...) {
doWithC(() -> ...);
doWithD(() -> ...);
}
// I am aware that a loop like this can cause a livelock.
// That's an aspect for another question, on another day.
}
There are multiple tasks like myTask above.
Tasks to be executed are wrapped in a closure and scheduled to a ThreadPoolExecutor (or something similar).
Approaches I considered:
Have singletons LockA, LockB, ...
Each doWithX is merely a synchronized(X) block.
OutXn are local variables of myTask.
Problem: One of the singletons is Swing, and I can't move the EDT into a thread that I manage.
As above. Solve the Swing problem from approach (1) by coding doWithSwing(){...} as SwingUtilities.invokeAndWait(() -> {...}.
Problem: invokeAndWait is generally considered prone to deadlock. How do I find out if I am into this kind of trouble with the pattern above?
Have threads threadA, threadB, ..., each of them "owning" one of the singletons (Swing already has this, it is the EDT).
doWithX schedules the block as a Runnable on threadX.
outXn are set up as Future<...> outXn = new SettableFuture<>(), the assignments become outXn.set(...).
Problem: I couldn't find anything like SettableFuture in the JDK; all ways to create a Futurethat I could find were somehow tied to a ThreadPool. Maybe I am looking at the wrong top-level interface and Future is a red herring?
With of these approaches would be best?
Is there a superior approach that I didn't consider?
I don't know the problem class nor the appropriate terminology
I'd probably just refer to the problem class as concurrent task orchestration.
There's a lot of things to consider when identifying the right approach. If you provide some more details, I'll try to update my answer with more color.
There are no constraints like "you must access B before you can do X with C" or similar.
This is generally a good thing. A very common cause of deadlocks is different threads acquiring the same locks in differing orders. E.g., thread 1 locks A then B while thread 2 owns the lock B and is waiting to acquire A. Designing the solution such that this situation does not occur is very important.
I couldn't find anything like SettableFuture in the JDK
Take a look at java.util.concurrent.CompletableFuture<T> - this is probably what you want here. It exposes a blocking get() as well as a number of asynchronous completion callbacks such as thenAccept(Consumer<? super T>).
invokeAndWait is generally considered prone to deadlock
It depends. If your calling thread isn't holding any locks that are going to be necessary for the execution of the Runnable you're submitting, you're probably okay. That said, if you can base your orchestration on asynchronous callbacks, you can instead use SwingUtilities.invokeLater(Runnable) - this will submit the execution of your Runnable on the Swing event loop without blocking the calling thread.
I would probably avoid creating a thread per singleton. Each running thread contributes some overhead and it's better to decouple the number of threads from your business logic. This will allow you to tune the software to different physical machines based on the number of cores, for example.
It sounds like you need each runWithX(...) method to be atomic. In other words, once one thread has begun accessing X, another thread cannot do so until the first thread is finished with its task step. If this is the case, then creating a lock object per singleton and insuring serial (rather than parallel) access is the right way to go. You can achieve this by wrapping the execution of closures that get submitted in your runWithX(...) methods in a synchronized Java code block. The code within the block is also referred to as the critical section or monitor region.
Another thing to consider is thread contention and order of execution. If two tasks both require access to X and task 1 gets submitted before task 2, is it a requirement that task 1's access to X occurs before task 2's? A requirement like that can complicate the design quite a bit and I would probably recommend a different approach than outlined above.
Is there a superior approach that I didn't consider?
These days there are frameworks out there for solving these types of problems. I'm specifically thinking of reactive streams and RxJava. While it is a very powerful framework, it also comes with a very steep learning curve. A lot of analysis and consideration should be done before adopting such a technology within an organization.
Update:
Based on your feedback, I think a CompletableFuture-based approach probably makes the most sense.
I'd create a helper class to orchestrate task step execution:
class TaskHelper
{
private final Object lockA;
private final Object lockB;
private final Object lockC;
private final Executor poolExecutor;
private final Executor swingExecutor;
public TaskHelper()
{
poolExecutor = Executors.newFixedThreadPool( 2 );
swingExecutor = SwingUtilities::invokeLater;
lockA = new Object();
lockB = new Object();
lockC = new Object();
}
public <T> CompletableFuture<T> doWithA( Supplier<T> taskStep )
{
return doWith( lockA, poolExecutor, taskStep );
}
public <T> CompletableFuture<T> doWithB( Supplier<T> taskStep )
{
return doWith( lockB, poolExecutor, taskStep );
}
public <T> CompletableFuture<T> doWithC( Supplier<T> taskStep )
{
return doWith( lockC, swingExecutor, taskStep );
}
private <T> CompletableFuture<T> doWith( Object lock, Executor executor, Supplier<T> taskStep )
{
CompletableFuture<T> future = new CompletableFuture<>();
Runnable serialTaskStep = () -> {
T result;
synchronized ( lock ) {
result = taskStep.get();
}
future.complete( result );
};
executor.execute( serialTaskStep );
return future;
}
}
In my example above withA and withB get scheduled on a shared thread pool while withC is always executed on the Swing thread. The Swing Executor is already going to be serial in nature, so the lock is really optional there.
For creating actual tasks, I'd recommend creating an object for each task. This allows you to supply callbacks as method references, resulting in cleaner code and avoiding callback hell:
This example computes the square of a provided number on a background thread pool and then displays the results on the Swing thread:
class SampleTask
{
private final TaskHelper helper;
private final String id;
private final int startingValue;
public SampleTask( TaskHelper helper, String id, int startingValue )
{
this.helper = helper;
this.id = id;
this.startingValue = startingValue;
}
private void start()
{
helper.doWithB( () -> {
int square = startingValue * startingValue;
return String.format( "computed-thread: %s computed-square: %d",
Thread.currentThread().getName(), square );
} )
.thenAccept( this::step2 );
}
private void step2( String result )
{
helper.doWithC( () -> {
String message = String.format( "current-thread: %s task: %s result: %s",
Thread.currentThread().getName(), id, result );
JOptionPane.showConfirmDialog( null, message );
return null;
} );
}
}
#Test
public void testConcurrent() throws InterruptedException, ExecutionException
{
TaskHelper helper = new TaskHelper();
new SampleTask( helper, "task1", 5 ).start();
new SampleTask( helper, "task2", 7 ).start();
Thread.sleep( 60000 );
}
Update 2:
If you want to avoid callback hell while also avoiding the need to create an object per task, perhaps you should take a serious look at reactive streams after all.
Take a look at the "getting started" page for RxJava:
https://github.com/ReactiveX/RxJava/wiki/How-To-Use-RxJava
For reference here's how the same example above would look in Rx (I'm removing the concept of task ID for simplicity):
#Test
public void testConcurrentRx() throws InterruptedException
{
Scheduler swingScheduler = Schedulers.from( SwingUtilities::invokeLater );
Subject<Integer> inputSubject = PublishSubject.create();
inputSubject
.flatMap( input -> Observable.just( input )
.subscribeOn( Schedulers.computation() )
.map( this::computeSquare ))
.observeOn( swingScheduler )
.subscribe( this::displayResult );
inputSubject.onNext( 5 );
inputSubject.onNext( 7 );
Thread.sleep( 60000 );
}
private String computeSquare( int input )
{
int square = input * input;
return String.format( "computed-thread: %s computed-square: %d",
Thread.currentThread().getName(), square );
}
private void displayResult( String result )
{
String message = String.format( "current-thread: %s result: %s",
Thread.currentThread().getName(), result );
JOptionPane.showConfirmDialog( null, message );
}

Can a non-thread-safe value be safely ported across thread boundaries using fork/join?

I have some class which is not thread safe:
class ThreadUnsafeClass {
long i;
long incrementAndGet() { return ++i; }
}
(I've used a long as the field here, but we should think of its field as being some thread-unsafe type).
I now have a class which looks like this
class Foo {
final ThreadUnsafeClass c;
Foo(ThreadUnsafeClass c) {
this.c = c;
}
}
That is, the thread unsafe class is a final field of it. Now I'm going to do this:
public class JavaMM {
public static void main(String[] args) {
final ForkJoinTask<ThreadUnsafeClass> work = ForkJoinTask.adapt(() -> {
ThreadUnsafeClass t = new ThreadUnsafeClass();
t.incrementAndGet();
return new FC(t);
});
assert (work.fork().join().c.i == 1);
}
}
That is, from thread T (main), I invoke some work on T' (the fork-join-pool) which creates and mutates an instance of my unsafe class and then returns the result wrapped in a Foo. Please note that all mutation of my thread unsafe class happens on a single thread, T'.
Question 1: Am I guaranteed that the end-state of the instance of the thread-unsafe-class is safely ported across the T' ~> T thread boundary at the join?
Question 2: What if I had done this using parallel streams? For example:
Map<Long, Foo> results =
Stream
.of(new ThreadUnsafeClass())
.parallel()
.map(tuc -> {
tuc.incrementAndGet();
return new Foo(tuc);
})
.collect(
Collectors.toConcurrentMap(
foo -> foo.c.i,
Function.identity();
)
);
assert(results.get(1) != null)
I think ForkJoinTask.join() has the same memory effects as Future.get() (because it says in join() Javadoc that is is basically get() with interruption and exception differences). And Future.get() is specified as:
Actions taken by the asynchronous computation represented by a Future happen-before actions subsequent to the retrieval of the result via Future.get() in another thread.
In other words, this is basically a "safe publication" via Future/FJT. Which means, anything that the executor thread did and published via FJT result is visible to FJT.join() users. Since the example allocates the object and populates its field only within the executor thread, and nothing happens with the object after it gets returned from the executor, it stands to reason that we are only allowed to see the values the executor thread produced.
Note that putting the whole thing via final does not bring any additional benefit to it. Even if you just did the plain field stores, you would still be guaranteed this:
public static void main(String... args) throws Exception {
ExecutorService s = Executors.newCachedThreadPool();
Future<MyObject> f = s.submit(() -> new MyObject(42));
assert (f.get().x == 42); // guaranteed!
s.shutdown();
}
public class MyObject {
int x;
public MyObject(int x) { this.x = x; }
}
But notice that in the Stream example (if we assume the symmetry between Stream.of.parallel and Executor.submit, and between Stream.collect and FJT.join/Future.get), you have created the object in the caller thread, then passed it to executor to do something. This is a subtle difference, but it does not matter much still, because we also have HB on submit, that preclude seeing the old state of the object:
public static void main(String... args) throws Exception {
ExecutorService s = Executors.newCachedThreadPool();
MyObject o = new MyObject(42);
Future<?> f = s.submit(() -> o.x++); // new --hb--> submit
f.get(); // get -->hb--> read o.x
assert (o.x == 43); // guaranteed
s.shutdown();
}
public static class MyObject {
int x;
public MyObject(int x) { this.x = x; }
}
(In formal speak, that is because all the HB paths from read(o.x) go via the action of the executor thread that does store(o.x, 43))

Why is CompletableFuture.supplyAsync succeeding a random number of times?

I'm new to both lambdas and asynchronous code in Java 8. I keep getting some weird results...
I have the following code:
import java.util.concurrent.CompletableFuture;
public class Program {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
String test = "Test_" + i;
final int a = i;
CompletableFuture<Boolean> cf = CompletableFuture.supplyAsync(() -> doPost(test));
cf.thenRun(() -> System.out.println(a)) ;
}
}
private static boolean doPost(String t) {
System.out.println(t);
return true;
}
}
The actual code is a lot longer, as the doPost method will post some data to a web service. However, I'm able to replicate my issue with this bare-bones code.
I want to have the doPost method execute 100 times, but asynchronously for performance reasons (in order to push data to the web service faster than doing 100 synchronous calls would be).
In the code above, the ´doPost´ method is run a random amount of times, but always no more than 20-25 times. There are no exceptions thrown. It seems that either some thread handling mechanism is silently refusing to create new threads and execute their code, or the threads are silently crashing without crashing the program.
I also have an issue where, if I add more functionality to the doPost method than shown above, it reaches a point where the method simply silently breaks. I've tried adding a System.out.println("test") right before the return statement in that case, but it is never called. The loop which loops 100 times does run 100 iterations though.
This behaviour is confusing, to say the least.
What am I missing? Why is the function supplied as an argument to supplyAsync run a seemingly random number of times?
EDIT: Just wanted to point out that the situation is not exactly the same as in the question this was marked as a possible duplicate of, as that question dealt with arbitrarily deeply nested futures, and this one deals with parallell ones. However, the reason why they are failing is virtually identical. The cases seem distinct enough to merit separate questions to me, but others might disagree...
By default CompletableFuture uses own ForkJoinPool.commonPool() (see CompletableFuture implementation). And this default pool creates only daemon threads, e.g. they won't block the main application from terminating if they still alive.
You have the following choices:
Collect all CompletionStage to some array and then make java.util.concurrent.CompletableFuture#allOf().toCompletableFuture().join() - this will guarantee all the stages are completed before going after join()
Use *Async operations with your own thread pool which contains only non-daemon threads, like in the following example:
public static void main(String[] args) throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(10, r -> {
Thread t = new Thread(r);
t.setDaemon(false); // must be not daemon
return t;
});
for (int i = 0; i < 100; i++) {
final int a = i;
// the operation must be Async with our thread pool
CompletableFuture<Boolean> cf = CompletableFuture.supplyAsync(() -> doPost(a), pool);
cf.thenRun(() -> System.out.printf("%s: Run_%s%n", Thread.currentThread().getName(), a));
}
pool.shutdown(); // without this the main application will be blocked forever
}
private static boolean doPost(int t) {
System.out.printf("%s: Post_%s%n", Thread.currentThread().getName(), t);
return true;
}

ForkJoinPool thread spawning new threads

Let's say that I have to run some (mostly independent) expensive tasks in parallel. Normally this can easily be done using the fork/join framework.
My problem is that, some of those tasks may also spawn subtasks, using a different ForkJoinPool (in some method deeper down in the call hierarchy). I know that this will spawn many threads, which may slow down my application, and I would like to avoid that. One solution is to use the global pool and add tasks there, but this is not an option in my case.
The reason this is useful for me is that some of the original tasks are dependent and may wait for each other. For example, say A1 and A2 are two tasks which need the results of B (which is parallelizable) in order to proceed to C1 and C2 respectively. In that case, the threads running A1 and A2 can focus on B to improve CPU utilization. A simple example is shown below.
ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
public int expensiveComputation(int x) {
int result = x;
// do stuff using different ForkJoinPool!
return result;
}
public abstract class A {
public abstract run(int x);
}
public class A1 extends A {
public A1(int x) {
super(x);
}
#Override
public void run() {
// do stuff
// Only 1 thread will run this for a given value of x
map.putIfAbsent(x, expensiveComputation(x));
// do stuff
}
}
public class A2 extends A {
public A2(int x) {
super(x);
}
#Override
public void run() {
// do stuff
// Only 1 thread will run this for a given value of x
map.putIfAbsent(x, expensiveComputation(x));
// do stuff
}
}
public static void main(String[] args) {
LinkedList<A> tasks = new LinkedList<>();
tasks.add(new A1(0));
tasks.add(new A2(0));
// More tasks
ForkJoinPool pool = new ForkJoinPool(parallelism);
pool.submit(() -> tasks.parallelStream().forEach((x -> {
x.run();
})));
}
Is it possible to utilize the "parent" pool from within those tasks? In the example above, the parent pool is the one in the main method.
Naturally, I would like to do this without passing it as an argument through a long chain of method calls or using a global variable. Ideally I would like to restrict my program to the number of threads used by the parent pool, without doing any such tricks.

How to isolate variables between threads in Java?

I think I'm having race conditions when running my multithreaded Java program.
It's a permutation algorithm, which I want to speed up by running multiple instances with different values. So I start the threads in Main class with:
Runnable[] mcl = new MCL[n1];
for (int thread_id = 0; thread_id < n1; thread_id ++)
{
mcl[thread_id] = new MCL(thread_id);
new Thread(mcl[thread_id]).start();
Thread.sleep(100);
}
And it runs those MCL classes instances.
Again, I think threads are accessing the same memory space of the MCL class variables, am I right? If so, how can I solve this?
I'm trying to make all variables arrays, where one of the dimensions is related to an Id of the thread, so that each thread writes on a different index. Is this a good solution?:
int[] foo = new foo[thread_id];
You can't just bolt on thread safety as an afterthought, it needs to be an integral part of your data flow design.
To start, research and learn the following topics:
1) Synchronized blocks, mutexes, and final variables. A good place to start: Tutorial. I also love Josh Bloch's Effective Java, which although a few years old has golden nuggets for writing correct Java programs.
2) Oracle's Concurrency Tutorial
3) Learn about Executors. You shouldn't have to manage threads directly except in the most extreme cases. See this tutorial
If you pass non thread safe objects between threads you're going to see unpredictable results. Unpredictable means assignments may never show up between different threads, or objects may be left in invalid states (especially if you've got multiple member fields that have data dependent on each other).
Without seeing the MCL class we can't give you any specific details on what's dangerous, but given the code sample you've posted I think you should take a step back and do some research. In the long run it will save you time to learn it the right way rather than troubleshoot an incorrect concurrency scheme.
If you want to keep the thread data separate store it as instance variables in the Runnables (initializing each Runnable before starting its thread). Don't keep a reference to it in an array, that's just inviting trouble.
You can use a CompletionService to get a computed value back for each task wrapped in a Future, so you don't wait for it to be calculated until you actually need the value. The difference between a CompletionService and an Executor, which the commentors are recommending, is that the CompletionService uses an Executor for executing tasks, but it makes it easier to get your data back out, see this answer.
Here's an example of using a CompletionService. I'm using Callable instead of Runnable because I want to get a result back:
public class CompletionServiceExample {
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
ExecutorCompletionService<BigInteger> service =
new ExecutorCompletionService<BigInteger>(executorService);
MyCallable task1 = new MyCallable(new BigInteger("3"));
MyCallable task2 = new MyCallable(new BigInteger("5"));
Future<BigInteger> future1 = service.submit(task1);
Future<BigInteger> future2 = service.submit(task2);
System.out.println("submitted tasks");
System.out.println("result1=" + future1.get() );
System.out.println("result2=" + future2.get());
executorService.shutdown();
}
}
class MyCallable implements Callable<BigInteger> {
private BigInteger b;
public MyCallable(BigInteger b) {
this.b = b;
}
public BigInteger call() throws Exception {
// do some number-crunching thing
Thread.sleep(b.multiply(new BigInteger("100")).longValue());
return b;
}
}
Alternatively you can use the take method to retrieve results as they get completed:
public class TakeExample {
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
ExecutorCompletionService<BigInteger> service = new
ExecutorCompletionService<BigInteger>(executorService);
MyCallable task1 = new MyCallable(new BigInteger("10"));
MyCallable task2 = new MyCallable(new BigInteger("5"));
MyCallable task3 = new MyCallable(new BigInteger("8"));
service.submit(task1);
service.submit(task2);
service.submit(task3);
Future<BigInteger> futureFirst = service.take();
System.out.println(futureFirst.get());
Future<BigInteger> futureSecond = service.take();
System.out.println(futureSecond.get());
Future<BigInteger> futureThird = service.take();
System.out.println(futureThird.get());
executorService.shutdown();
}
}

Categories

Resources