1

I am working on a spring boot project. I have a scenario where I need to make a service call, fetch data from DB and update a response object. I want to do these in two different threads in order to achieve better performance.

I tried using the following code

Thread t1 = new Thread(new Runnable(){

    public void run(){
        try {
            //make service call and update response object.
        }
        catch(Exception e){

        }
    }
    });

    t1.start();
    //fetch data from DB and update the response object.

    t1.join();

But this does not work when I try to hit the request and let it complete without putting any break points(basically executing it in the sequence that I want).

Is there a better alternative to achieve this?

Can I use fork and join here? If yes, how do I use it?

Please note that the data from service call and data from DB are not dependent on each other.

On further digging I found the below information in oracle documentation

http://www.oracle.com/technetwork/articles/java/fork-join-422606.html

First and foremost, fork/join tasks should operate as “pure” in-memory algorithms in which no I/O operations come into play. Also, communication between tasks through shared state should be avoided as much as possible, because that implies that locking might have to be performed. Ideally, tasks communicate only when one task forks another or when one task joins another.

11
  • can you please explain bit more "executing it in the sequence that I want" Commented Apr 10, 2018 at 15:59
  • What I am doing is putting a breakpoint on the line where I am quering the DB and executing the new thread part at first. once the call is done and the response is updated, I release the thread on DB. Commented Apr 10, 2018 at 16:02
  • So, what I understood that you have created 2 thread one is T1 to make service call another T2 for fetch data from DB. Now you want T1 will execute first and complete its task after that T2 will start its task. Am I right? Commented Apr 10, 2018 at 16:05
  • I want to execute both t1 and t2 simultaneously and wait for each other on completion. I did the above mentioned execution in order to check if the same object can be updated or not. Commented Apr 10, 2018 at 16:10
  • You could use an Executor to execute 2 FutureTask, the call to get() will be blocking. This should be the simplest solution, you could also check CyclicBarrier. Commented Apr 10, 2018 at 16:15

3 Answers 3

3

I think you do not need ForkJoinPool for that. You can use simply CountDownLatch. Main / parent thread will wait until the countdown to 0.

CountDownLatch latch = new CountDownLatch(2);
Thread t1 = new Thread(() -> {
    // do service call and update the response object 
    latch.countDown();
});
Thread t2 = new Thread(() -> {
    // do database call and update the response object 
    latch.countDown();
});

t1.start();
t2.start();

latch.await(); // main thread will wait here for the completion of T1 & T2 thread. 

Edited:

So handling the exception in a thread in a different way first way as below and it simple exception handling like we do.

Thread t1 = new Thread(() -> {
    // do service call
    try {
        // your code here
    } catch (Exception e) {

    }
    latch.countDown();
});

Another way is to use new Thread.UncaughtExceptionHandler() like below.

Thread.UncaughtExceptionHandler exceptionHandler = new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                //your exception handling code should come here
            }
        };

t1.setUncaughtExceptionHandler(exceptionHandler);

For more info about exception handling in Thread you can have a look on this

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

2 Comments

How do I handle Exceptions with this approach?
I have already done that. But the thing is I am not able to funnel the exception.
1

What you need is a CompletableFuture here. While the other answers will definitely work, CompletableFutures compose very well. There's also full support for that in Spring Boot; so you can return an CompletableFuture from a controller.

You can definitely write that as follows:

return CompletableFuture.supplyAsync(() -> {
        // call service
        return service.doCall();
 }).thenComposeAsync(result -> {
        // update DB and return original result
        db.update(result);
        return result;
 });

thenComposeAsync() will make sure that the DB update will run after the service call.

By default, this expression will run on ForkJoinPool but you can define which ExecutorService they run on.

1 Comment

Well I don't want it to be done after the service call. So I think this solution won't fit in.
0

Well first you go with the first example of the Doc you pass and saids::

Directly manipulating threads this way is fine for simple examples, but with concurrent programming, such code can quickly become error-prone, especially when several threads need to cooperate to perform a larger task. In such cases, their control flow needs to be coordinated.

So in the same Doc it suggest to use Executors:

Executors, which are an enhancement over plain old threads because they are abstracted from thread pool management. They execute tasks similar to those passed to threads (in fact, instances implementing java.lang.Runnable can be wrapped). Several implementations are provided with thread pooling and scheduling strategies. Also, execution results can be fetched both in a synchronous and asynchronous manner.

So change your simple Runnable thead to a Callable thread for getting a future variable and see how you can succes in that task:

The advantage of using Callable over Runnable is that Callable can explicitly return a value.

And check this answer for returning an Object for a Callabe

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.