Technical site for the tutorials related to Java, Spring Framework, College Projects, System Design, Hibernate /JPA, Microservices, Game Creation, Data Structures & Algorithm.
We can enable cache in spring by the use of @EnableCaching and @Cachable.
Refer Video Tutorial For Detail :
@EnableCaching
The annotation @EnableCaching should be used on the class level to configure the class for enabling cache. This annotation should be used to make it configurable for cache maintenance.
@EnableCaching //provided annotation on class level public class CachingDemo{ //Custom Code }
@Cachable
The annotation @Cachable should be used above the methods which needs to maintain cache.
Once the request is complete the response is stored in cache for same request coming in future.
The response is mapped to the key for further requests.
@Cacheable("userInfo") //provided cacheable annotation along with userInfo as key publicStringcheckCache() {
//Custom Code }
Conclusion
Major annotation to be used for caching in spring is @EnableCaching and @Cachable. The key should be provide where the cached is used so that the cache data should be mapped to the key.
In this lesson, we will see how we can use the executor service in a real-life scenario. We will use the worker threads to execute a task and thus reduce the processing time by using a thread pool.
Scenario:
Suppose you have to send emails to all the students of a college with their details.
Let's take some assumptions. Consider that it takes around 30 milliseconds to send mail to one student. Let the number of students be 1000. Considering in mind all these total time for sending mail becomes time multiplied with students count plus some delta time for processing extra code.
Assumptions:
The total number of students: 1000 students.
The time it takes to send mail for one student=30 milliseconds or 0.03 second.
Total time using single thread= 0.03 X 1000 + delta time for processing=30 seconds + delta time for processing.
Using Single Thread:
Let's create a single thread using newSingleThreadExecutor() method of ExecutorService. Create a thread which takes 30 milliseconds to execute its task.
class SendMail implements Runnable { public void run() { try{ Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } }
Run the task for 3000 times. For running with single thread the code will be like below.
We can print the date to find the time difference between start and end of the code to send mail.
It almost came out 30 seconds + some delta time due to processing.
Using Thread Pool:
Let's create a single thread using newFixedThreadPool(threadCount) method of ExecutorService. Create a thread which takes 30 milliseconds to execute its task.
class SendMail implements Runnable { public void run() { try{ Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } }
Run the task for 3000 times. For running with a thread pool of 10 worker threads, the code will be like below.
We can print the date to find the time difference between start and end of the code to send mail.
It almost came out 3 seconds using 10 worker threads due to processing.
Conclusion:
When a single thread is used to execute task it took more than 30 seconds. We created a thread pool of 10 worker threads, then it took almost 3 seconds. So we can create multiple threads using executor service and can reduce the time and increase the efficiency of a task in the project which requires a similar task to be done multiple times.
We can create our own custom exception in Java. This can be done by extending the Exception class of java.lang package. In other words, we need to import java.lang.Exception and extend this Exception class in our custom exception class.
Example :
First, create a class. In this case, our class is MyException which is extending the Exception class of java.lang package.
import java.lang.Exception;
/*extend Exception of java.lang package*/
class MyException extends Exception{
public MyException(String excStr){
/*Create a constructor and pass string argument */
super(excStr);
/*call the parent class constructor*/
}
}
To apply in the code use throws and pass the string as the perimeter. Here throw new MyException("Caught Sumit!") is used to throw the exception.
public class MyCustomException{
public static final String DETAILS_OF_LOGGEDIN_USER= " I am Sumit";
public static void main(String[] args){
try{
if(DETAILS_OF_LOGGEDIN_USER.contains("Sumit")){
throw new MyException("Caught Sumit");
}
}catch(MyException me){
System.out.println(me.getMessage());
}
}
}
The caught exception can be read by using getMessage() method of the Exception class.
In this case, the output will be the String passed in the Constructor of MyException class. So getMessage() method will print "Caught Sumit".
Submit() and execute() are the methods of ExecutorService in Java. One can assign any task in these methods for execution of a particular code block.
The Future interface:
The Future interface is used to get the return data of Callable and Runnable tasks. It has a method called get() so one can pass the result of submit() in the Future instance to track the output result.
Difference between submit() and execute():
Since both the methods can be used to perform a given task but major difference lies between the return type of both the method. The return type of execute() method is void so it returns null when data is passed in Future object.
So when execute() method is passed in Future then compile time error is shown.
But when submit() method is called no compile-time error is displayed and the code runs successfully.
One can track the execution of a code block in submit() method by getting the return data using get() method of future. But this is not possible in execute() method of ExecutorService as the return type of execute() method is void.
Types methods of submit() method:
There are two types of submit method. One with the Runnable and the other with the Callable interface.
submit(new Runnable): In which Runnable has the method public void run().
submit(new Callable): In which Callable has the method public Object call().
Difference between submit(Runnable) and submit(Callable) :
The return type is the main difference between the submit with Runnable and submit with Callable.
As the name suggests the Callable calls the data at the end and provides in the Future object.
As we can see Object is the return type in public Object call(). The object is the return type here and the "Got something in return with callable" got printed in the console.
But in the case of submit with Runnable the return type is void so "null" gets printed in the console
As one can see void is the return type here in public void run() so "null" is passed in the Future.
The concepts of the volatile key are often misunderstood and often explained in the wrong way. Providing the concepts in simple and in an easy to understand way.
What is volatile Key?
Volatile is a keyword which can be applied to a variable to perform basic synchronization.
To make a variable volatile provide volatile in the declaration of the variable.
Uses of volatile key:
Used to make operation on a variable like reading and writing through main memory.
It acts as the operations are performed in a synchronized block.
The value of a variable will never be caught locally.
Example :
To make use of volatile keyword just provide in the declaration only.
Below is the example where int data variable is used along with the volatile keyword.
Nowadays in some office, it is required to stay on your desk and work for office hours. The employees are being tracked depending upon the login hours on their systems. Sometimes it also happens that if someone is not on their desk for even 5 minutes then the information goes to the manager. So to avoid these scenarios it is better to make a utility class in java to make the random movement of the mouse pointer. This will let the admin assume that employee is on the seat. To make this type of utility we will use the Robot class of java.awt package and we will use the mouseMove(x,y) method of Robot class. x and y are the coordinates.
Below is the program to move the mouse from one corner to another diagonally.
import java.awt.Robot;
public class MyUtilityToMoveMouse {
public static void main(String... args) throws Exception {
int x = 0, y = 0;
boolean bool = true;
Robot robot = new Robot();
while (true) {
robot.mouseMove(x++, y++);
Thread.sleep(20); } } }
Below is the program to move the mouse in zig-zag fashion like the lifeline.
import java.awt.Robot;
public class MyUtilityToMoveMouse {
public static void main(String... args) throws Exception {
int x = 100, y = 400;
boolean bool = true;
Robot robot = new Robot();
while (true) {
robot.mouseMove(x, y);
if (bool) { x += 5;y += 5; } else { x += 5;y -= 5; }
if (y == 420) bool = false; else if (y == 380) bool = true;
Difference between Implements Runnable and Thread Class :
Since by extending Thread class we cannot inherit other classes. But in the case of Runnable Interface, we can implement as many interfaces as much as required.
When we create a thread using Thread class each time a new object is created. But in the case of the Runnable interface, it uses the same object for multiple threads.
The Runnable interface is preferred over the Thread class because of the above reasons.
Creating thread using Thread Class :
For creating a thread using Thread class extend the Thread class. Provide the code in run() method. Create the thread using new operator and call the start() method of Thread class.
class PlayExt extends Thread{ public void run(){ // code to execute } } public class MyExtend { public static void main(String[] args) { PlayExt pe = new PlayExt(); // create object using new operator pe.start(); // call the start method to run a thread } }
Creating thread using Runnable Interface :
For creating a thread by implementing the Runnable interface. Provide the code in run() method. Create the thread by providing the class which implements the Runnable interface in the constructor of Thread class and call the start() method of Thread class.
// can extend other class also class PlayRun implements Runnable{ public void run(){ // code to execute } } public class MyRunnable { public static void main(String[] args) { Thread pr = new Thread(new PlayRun()); // provide the in the constructor of Thread class pr.start(); // call the start mentod to execute thread } }
In Java, if-else statements are used to run codes on basis of boolean conditions. The conditions can be provided in the following ways :
if condition
if-else condition
if-elseif conditions
nested if conditions
If Statement :
In if condition a boolean condition is provided after if using "(" and ")".
/*syntax*/ if(booleanCondition){ // program to execute if booleanCondition is true }
Example :
Suppose if we have an int a whose value is 10. if we provide the boolean condition as "a==10" then it is a true statement. So if the input is :
int a=10; if(a==10){
System.out.println("If part executed!") ;
}
The output will be :
If part executed!
If-else statement :
In an if-else statement, if the condition of "if" block turns out to be false then else part is executed.
Suppose if the input is :
int a=10;
if(a>20){
System.out.println("If part executed!") ;
} else { System.out.println("else part executed!") ; }
The output will be :
else part executed!
If-elseif statement :
In an if-elseif statement, conditions are provided in the elseif part also. We can combine if-elseif with else also. So when all the conditions will fail else part will execute. Suppose if the input is :
int a=10;
if(a>20){
System.out.println("If part executed!") ;
} elseif (a>15){ System.out.println("elseif part executed!") ; } else { System.out.println("else part executed!") ; }
The output will be :
else part executed!
Nested If statements :
If one "if condition" is provided inside the outer if statement then it is known as nested if statement.
/*syntax*/ if(condition1){ // program executed if condition1 is true if(condition2){ // program executed if condition2 is true } }