Java is one of the most popular Object-Oriented programming languages offered by Oracle which has a wide range of applications in website and application development explored by developers. Java along with some well-known and robust frameworks like Spring, Spring-Boot, etc. makes developer’s life easy while developing/coding Software. Java offers 2 ways of Object Instantiation (Object Instance Creation) are namely Eager and Lazy. This Article focus on Non-Lazy Instantiation (which means Eager Instantiation).
Threads in Java are small individual coding units that can execute separately (in parallel fashion on multiple cores of CPU) to enhance processing speed etc. So Thread-Safe in java means no matter how much ever threads are created and executed simultaneously the output or business logic of the program execution stays as expected or desired. For a simple example like a Singleton (Only 1 instance should be present during the execution of code and new/different instances of this class are allowed to be instantiated except the creation of the first one) class in java
Thus, this article tries to throw light on non-Lazy-Instantiation in the Thread-Safe environment and helps explain it with a practical illustration of the car-maker (manufacturer) case study example.
Implementation:
The following would be the approach to demonstrate to explain non-Lazy-Instantiation of Object by taking a CarMaker.java (Script below) as an example.
- We have a Car java class (which acts as a Singleton Class), so only one object must be created and supplied across the entire flow of the program.
- We have a CarMaker class (Runner class which has the main() method in it), which tries to take base Car instance and performs operations like design, paint, and enhance with it (in our exact case these are simple print statements with appropriate messages)
- We are having separate Threads being created for all the operations mentioned above to demonstrate a Thread-Safe behavior (in our case this means no matter even if simultaneous threads reach getCarIntance() method, only one instance will be circulating around the program)
- The order of thread execution may change, but the outcome of having single object creation (will be visible with same object ID printed on the terminal) using non-Lazy Instance creation will be satisfied here.
Example
Java
// Java Program to illustrate Implementation of non // Lazy-Instantiation (Eager Instantiation) // which is Thread-Safe // Importing required libraries import java.io.*; import java.util.*; import java.util.concurrent.*; // 'CarMaker' class is trying to Manufacture a Car // So the Base vehicle 'Car' should remain same and // operations like paintCar,designCar,enhanceCar etc. // will execute with the same Car (Object Instance here.) // Class 1 // Helper class // Refers to a Singleton Class in General class Car { // Creating eager instance variable for Car // Thread-Safe as marked final private static final Car car = new Car(); // Only executes when new Car Instance is created // So Ideally this should be executed only once as // we are working with same Car // Constructor of Car class private Car() { // Print and display message // should be displayed only once on terminal. System.out.println( "New Car is Created" ); } // Method of Car class static Car getCarInstance() { // Returns the Car Instance return car; } } // Class 2 // Main class class CarMaker { // Main driver method public static void main(String args[]) { // We make threads dynamically for // each operation specified above // Thread 1 // Thread for designing the Car Thread designCar = new Thread( new Runnable() { // run() method for thread public void run() { // Creating and getting the Car instance Car car = Car.getCarInstance(); // Print and display the ID System.out.println( "Designing Car with id : " + car); } }); // Thread 2 // Thread for Painting the Car Thread paintCar = new Thread( new Runnable() { // run() method for thread public void run() { // Creating and getting Car instance by // calling the Car class method Car car = Car.getCarInstance(); // Print and display the ID System.out.println( "Painting Car with id : " + car); } }); // Thread 3 // Thread for Enhancing the Car Thread enhanceCar = new Thread( new Runnable() { // run() method for the thread public void run() { // Creating and getting Car instance by // calling the Car class method Car car = Car.getCarInstance(); // Print and display the ID System.out.println( "Enhancing Car with id : " + car); } }); // Note: Second object of Car class can not be // created Cannot create new Instance as Constructor // is not Visible // Below object is not created // in first compile and run // It is cleared here in second go // during compile and run // Car car2 = new Car(); // Running the above 3 threads as created above designCar.start(); paintCar.start(); enhanceCar.start(); } } |
Output:
Here we have compiled the program twice wherein the second time we have forcefully created the second ‘Car’ class object. Note that we can not create a second instance of the ‘Car’ class as the constructor for the second time is not visible. It will throw an error as depicted below in the pictorial hard-coded output in the underlined section which is thrown on the terminal as we compiled and run again by creating another object.
Output explanation:
Here in order to explain the non-Lazy Instantiation of Java class objects we take a simple case study of having a Car Marker who manufactures cars. It takes the base ‘Car’ vehicle and performs operations like Painting a Car, Designing a Car, and Enhancing the Car. To keep processing as simple as we can, we are having simple print statements in each operation along with the display of Car Object Id to make sure they are working on the same car.
As we can see in the output the order of execution for operations (Threads in this case) might differ, but the Car Object Id remains the same through the execution of the program to illustrate each operation (paint, design and enhance) is performed on the same car. As explained in the code comment “final” keyword at the singleton (Car) instance creation makes it thread-safe for execution, and thus we get the desired result of having the same Car Object throughout.
Conclusion: Do refer in order to figure out how “final” make the code thread-safe without having synchronization. Thus, the above article explains non-Lazy Instantiation (Eager Instantiation) of Java classes (Singleton classes) with the help of Car Maker case study example.