Tuesday, July 11, 2023

What is AtomicInteger?

The primary use of AtomicInteger is when you are in a multithreaded context and you need to perform thread-safe operations on an integer without using synchronized. The assignation and retrieval of the primitive type int are already atomic but AtomicInteger comes with many operations which are not atomic on int.

The simplest is the getAndXXX or xXXAndGet. For instance getAndIncrement() is an atomic equivalent to i++ which is not atomic because it is actually a shortcut for three operations: retrieval, addition, and assignation. compareAndSet is very useful for implementing semaphores, locks, latches, etc.

Using the AtomicInteger is faster and more readable than performing the same using synchronization.

For example, I have a library that generates instances of some class. Each of these instances must have a unique integer ID, as these instances represent commands being sent to a server, and each command must have a unique ID. Since multiple threads are allowed to send commands concurrently, I use an AtomicInteger to generate those IDs. An alternative approach would be to use some sort of lock and a regular integer, but that's both slower and less elegant.


A simple test:

public synchronized int incrementNotAtomic() {
    return notAtomic++;
}

public void performTestNotAtomic() {
    final long start = System.currentTimeMillis();
    for (int i = 0 ; i < NUM ; i++) {
        incrementNotAtomic();
    }
    System.out.println("Not atomic: "+(System.currentTimeMillis() - start));
}

public void performTestAtomic() {
    final long start = System.currentTimeMillis();
    for (int i = 0 ; i < NUM ; i++) {
        atomic.getAndIncrement();
    }
    System.out.println("Atomic: "+(System.currentTimeMillis() - start));
}


Thursday, June 8, 2023

Dispatcher Servlet

DispatcherServlet acts as the Front Controller for Spring-based web applications. So now what is Front Controller? So it is pretty simple. Any request is going to come into our website the front controller is going to stand in front and is going to accept all the requests and once the front controller accepts that request then this is the job of the front controller that it will make a decision that who is the right controller to handle that request. For example, refer to the below image. Suppose we have a website called student.com and the client is make a request to save student data by hitting the following URL student.com/save and its first come to the front controller and once the front controller accepts that request it is going to assign to the Controller_1 as this controller handle the request for /save operation. Then it is going to return back the response to the Client. 
So now you might be thinking about how to create a front controller in a Spring MVC Application? But the good news is, the front controller is already created by the Spring Framework Developer, and the name of that particular controller is DispatcherServlet. You can use that front controller in your Spring MVC project. You really are not required to create a front controller but you can reuse that front controller created by the Spring Framework Developer and they named it as DispatcherServlet. We can say



Spring caching

<<This document is for my own reference.  It helps me to remember these theories in the future. >>


First, we need to add the annotation "@EnableCaching" to the main method of the project.



The reason for using caching is to improve the system's performance. If you have saved data in the database and need to query data, you have to retrieve those values from the database each time request comes in. This could be a resource and time-consuming task. So the solution we have is, caching those data locally and passing it to the consumer if available in the local storage. 

We have to be very careful when we use this caching mechanism. Because, if we update/delete one value in the table we have to use specific annotations for those methods. Otherwise, cached data doesn't update and the consumer receives incorrect data.

Follow as below when retrieving data from the database. It caches all retrieved data.

According to the above sample code, name of the cache would be "books" and key would be "id". When you trigger this method, it first checks the key is exist in the "books" cache and if available, it doesn't execute the rest of the code.

How to update a value in the cache?

    







When you invoke the update method, specific cached values also get updated. "@CachePut" handles this task. Unlike in the "@Cacheable" annotation, this executes the rest of the code. 

How to delete a value in the cache?







"@CacheEvict" annotation takes care of removing existing cached values. If you don't use this annotation, cached values don't remove even it removed from the database.