Monday, November 26, 2007

Creating Threads: Extend Thread Class OR Implement Runnable Interface


1 Introduction
In this article I tried to answer the most common question regarding the creation of threads in Java: whether to implement Runnable interface or extend Thread class? While answering this question I also tried to cover the basic concepts involved in similar scenarios.

2 Whether to implement ‘Runnable’ interface or extend ‘Thread’ class?
In java sometimes we enjoy the liberty of implementing similar code in multiple ways. Although most of the times from a helicopter view we couldn’t figure out the subtle issues involved in each way unless we go into depth. The same holds true in this scenario as well.

In regard to the above question, I answer it in 3 parts.

1. Technical Constraint:
Although java supports multiple type inheritance, it doesn’t support multiple class inheritance. In other words, a class or interface can inherit from multiple inheritances, but a class can only inherit from one super class. Under this technical constraint, if a class extends ‘Thread’ class, it can’t extend any other class. Thus we loose the liberty of inheritance in this case. In view of this constraint, implementing ‘Runnable’ interface remain the only choice incase the class already inherit another class.

2. Semantic Difference:
Inheritance, being ‘is-a’ relationship, provides semantic definition of the class and categorize it to the category of the super class. Moreover incase of type (interface) inheritance, class or interface also provided with additional semantic ability. For e.g. when a class implements a ‘Serializable’ interface, it belongs to ‘Serializable’ category where it gets the ability to be serialized.

Thus in the above scenario, if your code semantically suitable to be categorized as a ‘runnable’ code which can run using a thread, it would be logical to implement the ‘Runnable’ interface. On the other hand, if your code is semantically like a thread in itself and can run itself as a thread, it would be semantically good to extend the ‘Thread’ class.

3. Implementation Difference:
The above two points are easy to understand and implement but at the last I would like to touch the most subtle issue involved in the above scenario.
Note that when we implement the ‘Runnable’ interface, our class is acting as a factory for creating threads. Thus all threads execute the run (and hence all non-static methods) of the same instance of the class. Thus if the run method of the class implementing ‘Runnable’ interface executes any synchronized method or block, all generated threads need to acquire lock of the same instance of the class. But incase of extending from the thread class, every new thread is a new instance of the class. Thus if run method internally executes any synchronized method or block, each thread needs to acquire lock on its own instance instead of any single instance. The explanation in this paragraph is depicted below in the figure.




To further explain this, let’s consider the code below:

public class RunnableClass implements Runnable {

public void run() {
m1();
}

public synchronized void m1() {
System.out.println("Lock acquired by [" + Thread.currentThread().getName() +"] Thread on instace: " + this);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public void m() {
Thread t1 = new Thread(this, "T1");
Thread t2 = new Thread(this, "T2");
Thread t3 = new Thread(this, "T3");
Thread t4 = new Thread(this, "T4");
Thread t5 = new Thread(this, "T5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}

public static void main(String[] args) {
new RunnableClass().m();
}
}


The output of this program would be similar to this:

Lock acquired by [T1] Thread on instace: com.test.general.RunnableClass@9304b1
Lock acquired by [T5] Thread on instace: com.test.general.RunnableClass@9304b1
Lock acquired by [T4] Thread on instace: com.test.general.RunnableClass@9304b1
Lock acquired by [T2] Thread on instace: com.test.general.RunnableClass@9304b1
Lock acquired by [T3] Thread on instace: com.test.general.RunnableClass@9304b1

Note that the id of the object on which lock is to be acquired by all threads is same. This evident that all threads will compete for the same lock hence if the run method internally calls synchronized method or block, the performance could be a major concern here.

Now look at the code below where ‘ThreadClass’ extends ‘Thread’ class.

public class ThreadClass extends Thread {

public ThreadClass(String name) {
super(name);
}

public void run() {
m1();
}

public synchronized void m1() {
System.out.println("Lock acquired by [" + Thread.currentThread().getName() +"] Thread on instace: " + this);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
new ThreadClass("T1").start();
new ThreadClass("T2").start();
new ThreadClass("T3").start();
new ThreadClass("T4").start();
new ThreadClass("T5").start();
}

public String toString() {

return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
}

The output of this program would be similar to this:

Lock acquired by [T1] Thread on instace: com.test.general.ThreadClass@9304b1
Lock acquired by [T3] Thread on instace: com.test.general.ThreadClass@a90653
Lock acquired by [T5] Thread on instace: com.test.general.ThreadClass@c17164
Lock acquired by [T4] Thread on instace: com.test.general.ThreadClass@1fb8ee3
Lock acquired by [T2] Thread on instace: com.test.general.ThreadClass@61de33

Note that the id of the object on which threads acquired lock is different. This means each thread needs to acquire lock on its own instance and hence if the run method internally calls synchronized method or block, threads need not to compete with each other to execute the same.

The above point suggests that incase the thread needs to execute some synchronized method or block, ‘extending Thread class’ could be a better solution.

3 Conclusion
Threads in java can be created in 2 ways. One can select an appropriate way depending on the hierarchy of the class, semantic definition of the class and execution of non-static synchronized code.

Friday, November 23, 2007

Singleton Pattern: The Unheeded Aspect

1 Introduction:
Singleton pattern is probably one of the most common design patterns being used in software development processes. It is also one of the simplest patterns from implementation and use perspective.

In this article I tried to light up some of the subtle facts regarding singleton pattern especially in java context. The aim of this document is to explore singleton pattern in depth especially the unheeded facts involved in it.


2 Singleton Pattern

2.1 A Quick Introduction:
Before putting forward some of the untouched features of Singleton pattern, let’s see a brief introduction of singleton pattern. Note that, although the definition quoted below is the most common definition of single pattern, the same is updated / changed below in this article when we explored singleton pattern in depth.

Definition: Singleton pattern assured that there will always be a single (one) instance of the class present in the run time environment.

Although, the above definition is the simplest to define singleton pattern, it indeed is neither complete nor correct. Before we explore the incompleteness and incorrectness of this definition, let’s see a simple way to implement singleton pattern (as per above definition) in java:

public class Singleton {

//The single instance of the class.
private static Singleton instance;

//Private constructor to avoid creation of multiple instances //from outside
private Singleton(){
}

//Static method returning the single instance of the class.
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}

}

Code Listing 1

The above code is as simple as the above definition. It explored a static method to get the single instance of the class. Also note that the constructor is private hence the class can’t be instantiated from outside. This will ensure that there will always be one instance of this class.

2.2 It’s Not Singleton Instance Pattern:
So the first incorrect word in the above definition is ‘single instance’. The pattern doesn’t restrict itself to the single instance, but to a single object (class or instance).

Look at the code below:

public final class SingletonClass {

//private constructor
private SingletonClass() {
}

//Static method
public static void method1(){
}

//All remaining methods are static
}

Code Listing 2

In the above code the class is final with optional private constructor and all methods as static. This will ensure that there will always be one class object corresponding to this class with no instance. This is another flavor of singleton pattern.

2.3 Java Doesn’t Support True Singleton Patterns:
Yes, this is a fact: java doesn’t support singleton pattern to its true flavor. So, the next incorrect word in the above definition is ‘run time environment’. Let’s discuss the issues involved in true implementation of singleton pattern in java.

1. Issues with Class loaders:
In java, a class loaded in JVM is recognized not only on the basis of its fully qualified name but also on the basis of the class loader responsible for loading it in the JVM. Thus if a singleton class is loaded with different class loader (the word class loader here refer to application/system class loaders or user defined class loaders extending application/system class loaders and also assuming that they are not in the same hierarchy), we will have that many instances (objects) of the class in JVM. In other words, while loading a class the JVM checks whether the same class is loaded by any class loader in the hierarchy or not. The class will be loaded only if none of the class loaders (in the same hierarchy) loaded the class. But incase the class loader is changed the same class will be reloaded and instantiated again provided the new class loader is not in the same hierarchy. Hence you may have multiple instances of a singleton class in the JVM using multiple class loaders.

Although this is a fact and has no solution, still it is an unheeded fact simply because of 2 reasons:

  1. Rarely we write our own class loader and use it to load the classes.

  2. Even in cases where a programmer writes his/her own class loader, most of the time he/she follows the same hierarchy.

Still it becomes a troubling issue many times for e.g. incase of web servers which uses new class loader for each Servlet even in the same web application.

2. Issues with Serialization:
Imagine a scenario where singleton class implements serializable interface. In such cases one can serialize and de-serialize the singleton instance of the class to get another instance in the same JVM. Although this is a rare situation and with proper implementation it can always be avoided, still it questions the implementation of true singleton pattern in java.

3. Issues with Threading:
In the code listing 1 above, imagine that multiple threads access the singleton class at the same time to get the instance for the first time. It might happen that these threads executes the line ‘if (instance == null)’ of getInstance() method at the same. This may result in creation of multiple instances at the same time. Although this is a result of wrong implementation of the entry method i.e. getInstance() but still depict the threading issues in java related with singleton pattern implementation. The above mentioned problem can be solved in 2 ways.
  1. Initialize the variable ‘instance’ at the time of declaration. But this will be against the optimized rule of lazy loading where the instance of the class is not creating unless it is required.

  2. The 2nd and most effective solution is use of either ‘synchronized’ block or method.

2.4 Few More Subtle Points Regarding Singleton pattern:
1. Issues with browser JVM incase of applets:
Although the issues vary from browser to browser, I am picking the most common MS Internet explorer and 2 most commonly faced issues related with singleton pattern incase of applets:

  1. If your page contains applet(s) which uses singleton patterns and you open a new window from this page (for e.g. using window.open() in java script), the same JVM will be shared between the parent and child browsers. In other words, the child browser will share the JVM of its parent and hence if the child browser too contains applet(s) and using the singleton class, note that the parent and child browser’s applet will use the same instance. Sometime this is a desirable condition but many a times it is categorized as a problem.

  2. On the other side of the coin there is an issue related with different frames on the same page. If your page is divided into frames and each frame has applet(s) using singleton pattern, then each frame will have its own JVM and hence the singleton instance will be per frame instead of per page.

2. Issues with distributed application:
In distributed environment, the application is deployed in fractions on different JVM and hence the singleton instances are not same throughout the code. Hence it is highly advisable to use singleton pattern in distributed environment in such a way that the same is restricted to one runtime environment. In other words the use of the singleton class should be logically categorized based on the code deployed on a single JVM instead of using the same singleton class across different runtime environment.

3. Issues with clustered environment:
Clustered environment, where multiple servers are used to serve the client requests, also brings lots of issues related with singleton classes. This becomes more prominent when the ‘Sticky Session’ approach is used where any server in the cluster can serve any request irrespective of the condition whether it or any other server has served the last request from the same client. In ‘Sticky Session’ approach all live sessions are replicated to all servers in the cluster and hence singleton instance creates problem when the session is replicated between servers. Thus one must be very cautious while using singleton pattern in clustered environment.

3 Conclusion:
Although one of the most simple and commonly used design pattern, singleton pattern has many subtle issued associated with it especially in java platform. One must take a judicious decision while using pattern and should considered all possible consequences before implementing singleton pattern in the application.

Monday, November 5, 2007

Gr8 Tips for Design

Design adds value faster than it adds cost --Joel Spolsky

Design has always been the most critical and prominent phase of a software development process. A good design not only ensures smooth implementation but also provides enough flexibility to accommodate future changes.

The aim of this article is to provide some useful tips which can help confirming a good design. This article shouldn’t be read as a tutorial to master the design or deeply understand every aspects of design, instead it should be used as a reference to confirm the wellness of your design. The article is structured with tips for good design along with few questions in each section which confirms whether the design follows the underlying principles or not. This unique way makes it easy to use this document as a final check list to affirm the quality of the design.

1. Modularization
One of the first goals towards a good design is to keep the modules of the application as logically divided units, each corresponding to a specific business need. The system should be designed in the way that the logical separation between modules is maintained in conjunction with the re-usability of the common logic and code. In large applications modularization become more prominent and unavoidable.

To confirm whether your design is modular or not, answer yourself the following questions:

  1. With this design, can we distribute the application, in a workable format, with the addition or removal of one or more modules of the application (obviously keeping logical dependency in mind)?
  2. Is the successful execution or failure of one module doesn't impact the execution of other modules?
  3. Can we add/remove/change a module in the system without majorly affecting other modules?

If answers to these questions are ‘yes’ or 'nearly yes', your design is modular in nature.

2. Reusability
Reusability of the design, code and logic is one of the salient measures of a good design. The increased reusability of the code assures centralization of logic and hence lesser efforts towards changes.

To confirm whether your design has reusability feature, you can ask following question to yourself:

  1. Have we used the same design to accomplish similar business functionalities?
  2. Have we designed so as to reuse the same code for the similar business or application logic? OR Is our logic is centric and reused at multiple places wherever required for e.g. central logic for logging,/auditing error handling, localization and so on?
  3. Have we used Abstraction, Inheritance and factory pattern, wherever applicable, to ensure reusability ?

If answers to these questions are ‘yes’ then you are definitely in the category of reusable design.

3. Loose coupling
Loose coupling, in broad way, indicates that the two components/tiers/layers, while communicating with each other, are not impacted with changes in other provided the communication protocol is not changed. Loose coupling can even be extended to the situations where the two components/layers/tiers lie in different technologies, languages or platforms. Interface based design in object oriented programming languages and Service Oriented Architecture are few examples where loose coupling is implemented to ensure these characteristics.

To confirm whether your design is loosely coupled, ask following following questions:

  1. If we change the implementation of a particular component or tier (web, business, persistent), the other components or tiers in the system don't need any change?
  2. If we choose different technology or platform for one tier, it doesn't require any internal changes in other tiers (except the code responsible for establishing communication channel for e.g. service locator)?
  3. Have we used ‘interface based programming’, business delegate and service locator patterns to ensure the loose coupling in code?

Positive answers to these questions indicate loose coupling of design.

4. Changeability
‘Change’, as we all know, is an unavoidable and the most expected happening in software life cycle. The change could be in business requirements, underlying technology/API/tools, or even in design/architecture. Although being stated as the most expected thing to happen in software life cycle, designer has to take a judicious approach to provide flexibility for changes in design, so that neither it is too much flexible to anticipate huge changes nor it should be too arduous to accept any change in future. Many times, domain and business understanding of the product, discussion with product management team and thorough product understanding can help in taking this decision.

To confirm whether the design is changeable, the designer can ask himself the following questions:

  1. Will it take least possible effort to accommodate a feasible change in business or technical requirements of the application?
  2. Have we kept the logic of (anticipated) changeable business functionality at a center location so that changes here resulted in least impact on rest of the code?
  3. Is our design loosely coupled with the frameworks, 3rd party API, containers, servers and other outer entities, so that changes in any of those don’t impact our design?

If answers to these questions are ‘yes’, your design also has 'changeable' feature.

5. Scalability and Plug-ability
A good design provides scalability with ease. The term scalability, in general sense, indicates the capability of the system to perform well in the situations of high data volume or users or service requests. A good design should always be done keeping in mind the scalability aspect of the application. A slightly related feature is functional/technical extendibility, which indicates the capability to add new application functionality or a technical features with ease. An example of technical extendability could be a good I18N framework, which uses .properties file as resource bundle but provided with felxibility to extend code to consider XML or txt files as resource bundles in future.

On the similar line, plug-ability allows adding new functionalities or features in the system on the lines of already existing features for e.g. a good web application could be designed in such a way that a new module could be added by adding a jar file and minimal configuration.

To confirm whether the design is Scalable and Pluggable, the designer can ask himself following questions:

  1. Have I used polymorphism and other relevant practice to make sure that the use of functionality is not tightly couple with its implementation, so that I can provide room for scalability of the code?
  2. Have I provided sufficient API for the functionalities to be extended?
  3. Have I provided room in the design to incorporate other features as pluggable in the system?

If answers to these questions are ‘yes’ then the designer can affirm that the design is scalable and pluggable.

6. Robustness and Stability
A robust and stable design ensures that the system won’t crash or fail in any condition whether it is favorable or disastrous. In other words, the system will handle all inputs gracefully whether in correct or incorrect format.

To confirm whether the design is robust and stable or not, the designer can ask following questions himself:

  1. Have I handled all possible erroneous conditions in the system?
  2. Have I designed comprehensive test cases to make sure that the system is unit tested against all possible input information?

If answers to these questions are ‘yes’ then the designer can affirm that the design is robust and stable.

7. Configurability
One of the biggest challenges in design is to make sure that the system will run equally good in heterogeneous environment by simply changing the configuration accordingly. Providing configurability in design means externalization of static and external information (may be in some xml file) so that the same can be changed without the need of any code change or even re-deployment in best cases. For an example, in an application requiring DB connectivity, the information like DB URL, driver class name, user/password etc can be externalized to some XML or text file so that it can be changed at runtime without the need to redeploying the application or any code change.

To confirm whether the design is configurable or not, the designer can ask following questions himself:

  1. Have I externalize all static and external information in the system?
  2. Does any change in the external information like DB, JDK version, XML Parser/Transformer/Data Binder, log and audit file etc can be accommodate in the system without any code change?
  3. Is the mechanism for gathering external information like GUI or XML file, is capable enough of holding complete required information?

If answers to these questions are ‘yes’ then the designer can affirm that the design is configurable.

8. Testability
The last but not the least is testability feature in the design. Unit testing has become one of the basic requirements for the success of the software. The design should provide room to accommodate testability in the same. As the word explains itself, testability feature makes the environment easy to plan, compose and execution of test cases to test all functionalities at unit level.

To confirm whether the design is testable or not, the designer can ask following questions himself:

  1. Is the design provides easy environment to execute test cases to test all features in the application at unit level?
  2. Is the design compatible with the other unit testing framework like JUnit?

If answers to these questions are ‘yes’ then the designer can affirm that the design is testable.

An important point to note at the last is that, although categorized in separate sections, the above principals are closely related and dependent on each other. For e.g. the reusability not only avoids code duplication but also increases the changeability in the system. Similarly testability increases the robustness and stability of the design. Hence the principals are tightly coupled with each other and should be considered as complement of each other.

In the last I would like to quote Sir Kevin Mullet’s great statement:

The most powerful designs are always the result of a continuous process of simplification and refinement.

My Picture