How I implemented Multithreading and reduced my API time from 4s to <100ms

How I implemented Multithreading and reduced my API time from 4s to <100ms

An elaboration to a very basic problem I'd encountered

ยท

4 min read

Before we start let's break this down into a few sections:

  • Why did the problem occur?
  • Solution that I implemented
  • Thread-safety?

I've tried my best to make it as generic and language independent as possible but I've added some Java code since I worked on this project using Java-Spring Boot.

I implemented this on a production application from one of my projects.

Why did the problem occur?

To give a little bit of context, my API has 2 services and a repository called from a single service. Let's name them service1, service2, repository1 and mainService.
The time to complete service1 and repository1 was <100ms whereas the time to complete service2 was about 3.5-4.5 seconds. Both these processes were quite important and I couldn't ditch the process carried by service2.

For readability, let's name service1 + repository1 as process1 and service2 as process2.


So, I took some time to figure out what was happening. process2 had very little logic(pretty much passing the parameters to the right method) and was primarily based off a library I was using. I started exploring the library and figured there was not much that could be done, since I figured the tasks it was executing were necessary.
But, I also noticed that both my processes(process1 and process2) were independent of each other. An idea struck my head.

On a side note: the library is the JavaMailSender.

Solution that I implemented

All I had to do was somehow have process2 run on a separate thread and have my main thread return the result after process1.
So I started exploring my options, I could use Java's CompletableFuture class. This worked perfectly but since I was using Spring Boot, I wanted to check if there was any other way of pushing process2 into being a background task and I found a solution. This solution had its advantages:

  • I could rely on 2 annotations to finish my task.
  • Since I didn't want my caller thread to wait for any kind of response, I could use this.

If I had to work with a certain response, I would rather prefer using CompletableFuture.

So what were these annotations? It is a simple @EnableAsync on top of my @SpringBootApplication and an @Async annotation on top of the method I was calling. You can read more about it here.

Java is synchronous. To achieve multithreading, java uses Asynchronous calls.

The @EnableAsync annotation enables our spring boot application to process asynchronous code.

@EnableAsync
@SpringBootApplication
public class ClassName {

    public static void main(String[] args) {
        SpringApplication.run(ClassName.class, args);
    }

}

Now let's add the @Async annotation on top of the method that is being called(in this case, sendMailFromServer). This allows running this method on a separate thread and as a background task when invoked.

@Async("emailThreadPool")
public void sendMailFromServer(){
    //code
}

I created a new thread pool, and I provided the name in the attribute for @Async.

And ta-da we are done! ๐Ÿš€

Note: I also checked if the library I was using was thread-safe or not.

Thread-safety?

An obvious question that comes to our mind after this: Is this really thread-safe? Let's understand this in a little detail.
Multithreading is really cool and helpful but it does come at a price, one very usual scenario is when multiple threads access the same resource, and if not handled well this can cause errors and might as well crash your entire application. Avoiding such situations by handling errors properly and by writing quality code creates a thread-safe application.
We can achieve the above said in the following ways:

  • Stateless-implementations
  • Immutable Implementations
  • Thread-Local Fields
  • By using Synchronized Collections or Concurrent Collections (Java)
  • Using the synchronized keyword at the method level.

I hope this was helpful! I'm also attaching a few resources below for you to read if you'd like!

Resources

ย