Saturday, November 22, 2014

Java Thread IV: BlockingQueue to Print Odd/Even Numbers

Today, we will see how to print odd even numbers using Blocking Queue.  

We want to print odd even numbers using two different threads and so it will obviously require some kind of thread synchronization to communicate while one thread is printing the number. So one thread will become producer (odd) and other one (even) will become consumer. Java provides BlockingQueue for thread synchronization in these kind of scenarios. 

BlockingQueue provides functions to support operations that awaits for the queue to become non-empty while retrieving elements or wait for the space to become available while inserting the elements.

In our example, we will use LinkedBlockingQueue which uses ReentrantLock (refer my earlier post) internally for thread synchronization. To implement the solution for our odd even thread, we will need two classes: TakeAndOfferNext class which is callable thread and OddAndEvenSignalling which will invoke the thread.

TakeAndOfferNext:

Now let's see the implementation of TakeAndOfferNext. We will need two blocking queues here: one for odd numbers and another one for even numbers.

    BlockingQueue takeFrom;
    BlockingQueue offerTo;

Blocking queue offers two synchronous operations called take() and offer(e). Take removes the element from the queue if it's non-empty and offer inserts to the queue if it's not full. Here, you dont' need to be aware of thread synchronization as blocking queue will take care of it through these two methods. So let's print odd even numbers using these blocking queues:

    public void print()    {
        while (true)  {
            try   {
                int i = takeFrom.take(); //removes the value in the "from" queue

                System.out.println(Thread.currentThread().getName() + " --> " + i);

                offerTo.offer(i + 1);    //increments the value by 1 and puts it in the "to" queue.

                if (i >= (maxNumber - 1)) {
                    System.exit(0);
                }
            } catch (InterruptedException e) {
                throw new IllegalStateException("Unexpected interrupt", e);
            }
        }
    }

As you can see here we are looping through the continuous loop until it reaches the max number. In the loop, we first take the first number (odd one) from the first queue and pass the next number (even one) to the another queue.

Okay, half work is done now how do we take even element from the another queue which we set at the end ? Well, we will need two threads to do this job which will switch the odde and even queues alternately in below class.

OddAndEvenSignalling:

        BlockingQueue odds = new LinkedBlockingQueue();
        BlockingQueue
evens = new LinkedBlockingQueue();
        ExecutorService executorService = Executors.newFixedThreadPool(2);

Now, our two threads are ready to print odd and even numbers. So, let's pass it on to the TakeAndOfferNext class in such a way that it will switch odd and even queues in the print() method.

        executorService.submit(new TakeAndOfferNext(odds, evens, MAX_NUMBER));
        executorService.submit(new TakeAndOfferNext(evens, odds, MAX_NUMBER));

And that's it, your job is done !!!

Working code samples can be found here.


You can try producer consumer example using blocking queue as an exercise.

Monday, November 3, 2014

Java Design Patterns II: Command Pattern to get rid of ugly if else blocks in Java

In my career, I came across many legacy applications and code and saw many bizarre code samples because it has been served by many different programmers over the period and everybody was probably lazy or under pressure to meet the deadline !!!

I personally hate ugly code and have very bad habit of re-factoring it on the spot whether it's bad naming conventions, incorrect formatting, duplicate code or hard coded string literals etc. because I  cannot just read through it without that. One of the thing I observed constantly in all those applications was code duplication and abuse of if-else blocks. 


Many programmers just love if else blocks simply because it's convenient to satisfy business logic quickly. There is nothing bad in it because it's very common to have multiple conditional logic in your business requirements but it starts getting ugly when you try adjusting tens (or sometimes hundreds, yes that's right) of conditions in one method or class using if-else blocks. 


In one of my recent assignments, we had to write pseudo SWIFT parser to process trade instructions and convert SWIFT message to XML. It was obvious that we had to write Parser to convert all the SWIFT tags (around 200 tags) into XML after doing some processing on each of the swift tag. Here is the sample code we had in it's original form....



public void uglyMethodWithNastyIfElseBlocks(String tagName){
             
   if(tagName.equals("NetAmount")){
       System.out.println("Doing something with NetAmount and having value :32B:");
   } else if(tagName.equals("GrossAmount")){
      System.out.println("Doing something with GrossAmount and having value :32M:");
   } else if(tagName.equals("SecurityId")){
       System.out.println("Doing something with SecurityId and having value :35B:");
   }
   .
   .
   .
   .
   } else {
       System.out.println("No Tags Found");
   }
}

Now imagine you have around 100 odd tags and doing some of processing on all of them which are accommodated inside same method. So to avoid this kind of situations Java provides you Command Pattern.

Now, lets re-factor this class using Command Pattern. To achieve clean code we will need one interface TagValueProvider to define the command for each tag which is currently inside if-else blocks, Enumeration: TagEnumeration to define Tag properties and Mapper class to map Tags with it's concrete implementation:

TagValueProvider: Each tag with different  behavior will implement below command.

      public void processTag(TagEnumeration tag);

ReturnTagValueProvider: Concrete implementation of each command.

@Override
public void processTag(TagEnumeration tag) {
System.out.println("Doing something with "+ tag.NETAMOUNT.getTagName() +" and having value " + tag.NETAMOUNT.getTagValue());

}

TagEnumeration: Each tag will have it's own properties and so will be mapped in this enumeration.

NETAMOUNT("NetAmount", ":32B:"), //key value pair of tags
GROSSAMOUNT("GrossAmount", ":32M:"),

SECURITYID("SecurityId", ":35B:");

TagMapper:  Schema to map the tags with implementing class. So you can have multiple tags mapping with common class or separate class having specific implementation.


  public static Map tagSchemaMapper = new HashMap();

static {
tagSchemaMapper.put(TagEnumeration.NETAMOUNT, new ReturnNetAmount());
tagSchemaMapper.put(TagEnumeration.GROSSAMOUNT, new ReturnGrossAmount());
tagSchemaMapper.put(TagEnumeration.SECURITYID, new ReturnSecurityId());
}

Now, let's see how our ugly method will look like after this re-factoring in below case.

public void correctMethodWithCommandPattern(TagEnumeration tags){
TagMapper.tagSchemaMapper.get(tags).processTag(tags);
}

So as you can see your multiple if else blocks will be replaced with single statement since command for each tag is now moved to concrete classes.

This is much cleaner approach because you don't have to accommodate entire business logic in one single method and more importantly it provides more readability to the code since each tag will have it's concrete implementation.

Advantages:
Separate implementation of each command with interface.
Enumeration to define each tag and it's properties.
HashMap to map the tag with it's behavior.

Saturday, November 1, 2014

Java Desing Patterns I: Chain Of Responsibility For Trade Enrichment.

Sometime back in one of the interviews with top Investment Bank, I was asked to write top level design diagram and highlight Interfaces, Classes and important mehthods.

Below is the detailed problem statement:

1. Trade domain objects may be enriched to add further information.
2. There are many different types of enrichment which may be carried out on a trade. 
     Party & Booking enrichment are two specific types of Enricher.
3. All enrichment is done normally at certain point in Trade processing (e.g. multiple Enrichers operating sequentially on Trades). This must be done via single Enricher.
4. It may be important to control the order of some Enrichers.

This is smart question because it makes you think and touches upon few of basic core java concepts like: Open Closed principle, Program against interface and also your design pattern knowledge on Strategy & Chain Of Responsibility but most importantly it checks your analytical and designing skills.

I liked the question because it's smart, simple and yet tricky. It's much better than asking singltons & hashmaps and all those useless questions which are repeatedly asked over and over again and people still think knowing these concepts can only make them smart coders !!

Till, first two points, I was sure they are asking me to explain Strategy pattern and will be straight forward but when I read 3rd point, I was sure they are asking something tricky which needed to be done with combination of some design patterns.

After putting my analytical skills in action for couple of minutes, I realized they are indirectly asking me to implement Chain Of Responsibility to check my designing skills. So here is what I came up with:

We will mainly need one interface (TradeEnrichment) to define enrichment and two concrete implementations: BookingEnricher & PartyEnricher.

public interface TradeEnrichment {

public void enrichment(TradeAccount tradeAccount);

public void setNextEnricher(TradeEnrichment nextEnricher);

}

Here, second method is important because it will provide us order of execution. Now, let's see one concrete implementation of this interface as asked in the question.


public class BookingEnricher implements TradeEnrichment {


TradeEnrichment enricher;

@Override
public void enrichment(TradeAccount tradeAccount) {

System.out.println("Enriching The Trade Booked");

if(enricher != null)
this.enricher.enrichment(tradeAccount); // call next enrichment
}

@Override
public void setNextEnricher(TradeEnrichment nextEnricher) {
this.enricher = nextEnricher;
}

}

Here, I have provided dummy implementation of Booking enrichment. Important thing to note here is the last statement which calls next Enricher in the sequence. So after completing the job Enricher simply passes the call to next Enricher in the sequence set using setNextEnricher() method.

Now, using Strategy Pattern here we can make sure that TradeEnrichment can have any number of concrete implementations in future as required and so our design follows Open-Closed principle (Open for enhancement but closed for modifications)

We will also need one class to invoke all these components and control sequencing order for the Trades: EnrichmentProvider.


public class EnrichmentProvider {

TradeEnrichment firstEnricher;

public void EnrichmentProvider(){

this.firstEnricher = new BookingEnricher();
TradeEnrichment secondEnricher = new PartyEnricher();

/** 
* set enrichment sequence here. you may have N number of enrichers in                                futures and you can control 
* the order of sequence here without impacting actual implementation in                             TradeEnrichment.
*/
firstEnricher.setNextEnricher(secondEnricher);

}

public static void main(String[] args) {

EnrichmentProvider tradeEnrichmentProvider = new EnrichmentProvider();

TradeAccount account = new TradeAccount();
account.setTradeType(TradeType.BOOK);

tradeEnrichmentProvider.firstEnricher.enrichment(account);
}

}

As you can see we are controlling the order of enrichers in the constructor by setting the next enricher in the chain.

Interviewers were quite impressed with clear understanding or design concepts and ability to craft clean interfaces because it helps  to discuss problems in terms of design patterns during design sessions and building new softwares. You don't have to explain your team how you will set order, how you can keep your implementations open for enhancements but closed for modifications etc. All you need to tell them is use Strategy Pattern & Chain Of Responsibility for Trade Enricher to control the order here and your job as a manager or architect is done, provided, you have hired right tech resource !!!!

Working code can be found here.

Friday, October 31, 2014

Java Thread III: Producer Consumer Using Synchronization vs Locks

Producer Consumer has always been favorite question in java multi-threading interviews.

We will create threads using two ways: Using usual synchronization & Locks.

Synchronization:\

Synchronization is standard way of locking shared resources and provide multi-threading. We  will create here two inner classes: Producer & Consumer and will use Stack to share the resources.

Producer:

class Producer extends Thread {


@Override
public void run() {
while (true) {
synchronized (itemStack) {
if (itemStack.size() <= MAX) {
COUNTER++;
itemStack.push(String.valueOf(COUNTER));
System.out.println("producing item ->" + COUNTER
+ " & size of stack is now :: "
+ itemStack.size());
itemStack.notifyAll();
}

while (itemStack.size() == MAX) {
try {
System.out.println("Stack is full & Producer is waiting.");
itemStack.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

}

Consumer:

private class Consumer extends Thread {


@Override
public void run() {
while (true) {
synchronized (itemStack) {
if (itemStack.size() != EMPTY) {
System.out.println("Consuming item ->"
+ itemStack.pop()
+ " & size of stack is now :: "
+ itemStack.size());
itemStack.notifyAll();
}g

while (itemStack.size() == EMPTY) {
System.out.println("Stack is empty & Consumer is waiting.");
COUNTER = 0;
try {
itemStack.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}

}

As you can see here, we are trying to acquire the lock using synchronization on shared object Stack.

NOTE: Make sure you declare itemStack as static variable or else both threads will deadlock each other.

Working code can be found here.

Lock:

Now let's see how we can rewrite same example using ReentrantLock object which is provided in java.util.concurrent package in jdk 5.


Please see my earlier post on Reentrant Lock if you are new to Lock concepts.

To rewrite producer consumer example using Lock, we will need below piece of code.

    private static Lock lock = new ReentrantLock();
    private static Condition hasSpace = lock.newCondition();
    private static Condition hasItems = lock.newCondition();

First line will create explicit lock object for our example and rest of two lines will provide the conditions required to synchronize the Stack.

Condition objects provides await(), signal() & signalAll() methods similar to wait(), notify() and notifyAll() provided by Object class.

Now, Lets see how we can leverage all of this in our example below.

private class Producer extends Thread {

@Override
public void run() {
while (true) {
try {
lock.lock();
while (itemStack.size() >= MAX) {
System.out.println("Stack is full & Producer is waiting.");
try {
// wait for the list to have space
hasSpace.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

COUNTER++;
itemStack.push(String.valueOf(COUNTER));
System.out.println("producing item number -> "
+ itemStack.size());
hasItems.signalAll();

} finally {
lock.unlock();
}
}
}
}

private class Consumer extends Thread {

@Override
public void run() {
while (true) {
try {
lock.lock();
while (itemStack.size() == EMPTY) {
System.out.println("Stack is empty & Consumer is waiting.");
try {
COUNTER = 0;
// wait for the list to have space
hasItems.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
itemStack.pop();
System.out.println("consuming item number -> "+ itemStack.size());
hasSpace.signalAll();
} finally {
lock.unlock();
}
}
}

}

So As you can see now,  we are acquiring the lock explicitly at the beginning of run() method and releasing it in finally block. Also, lock object provides separate conditions for Producer & Consumer objects as well and simplifies the code further because you know here which condition should await and which one should be signaled. (Check synchronized version for wait & notify conditions to compare against).

It provides more readability to synchronization code since now you have separate object for locking and so you know what exactly you are synchronizing on. In synchronized version, remember, we were relying on Stack object for locking and sometime this can lead to more confusion and can create deadlocks as well. (Hint: try synchronized version with Stack object as non-static reference.)

However, here since locking is explicit, you need to be alert to unlock the lock object at the end of it can create issues later in the code.

Working code can be found here.

Hope, this will help you understand synchronization and locking concepts.

Thursday, October 30, 2014

Java Thread II: Reentrant Lock Vs Synchronized

Today we will see the difference between Lock and Synchronized block but before we go into details, let's understand what is Lock and how it works.

What is Lock ?

Lock interface was introduced in jdk 1.5 along with other concurrency utilities like countdown latch etc. ReentrantLock is the main concrete implementation of lock interface which behaves as mutually exclusive lock like synchronized block.
So the next question comes in mind is why, or most importantly when, one should prefer Lock when we already have synchronized. There are some trade offs between these two and Reentrant Lock can be used in couple of conditions.
For example, Lock provides explicit locking and so it has more readability comparing to synchronized. You will see this in below examples.

1. Fairness:

The ReentrantLock constructor offers a choice of two fairness options: create a non-fair lock or a fair lock. With fair locking, threads can acquire locks only in the order in which they were requested, whereas an unfair lock allows a lock to acquire it out of its turn. This is called barging (breaking the queue and acquiring the lock when it became available).

Fair locking has a significant performance cost because of the overhead of suspending and resuming threads. There could be cases where there is a significant delay between when a suspended thread is resumed and when it actually runs. Let's see a situation:

A -> holds a lock.
B -> has requested and is in a suspended state waiting for A to release the lock.
C -> requests the lock at the same time that A releases the lock, and has not yet gone to a suspended state.

As C has not yet gone to a suspended state, there is a chance that it can acquire the lock released by A, use it, and release it before B even finishes waking up. So, in this context, unfair lock has a significant performance advantage.

2. Polled and Timed Lock Acquisition: 

Let's see some example code:

public void transferMoneyWithSync(Account fromAccount, Account toAccount,
   float amount) throws InsufficientAmountException {
  synchronized (fromAccount) {
   // acquired lock on fromAccount Object
   synchronized (toAccount) {
    // acquired lock on toAccount Object
    if (amount > fromAccount.getCurrentAmount()) {
     throw new InsufficientAmountException(
       "Insufficient Balance");
    } else {
     fromAccount.debit(amount);
     toAccount.credit(amount);
    }
   }
  }
 }

In the transferMoney() method above, there is a possibility of deadlock when two threads 

A and B are trying to transfer money at almost the same time.
A: transferMoney(acc1, acc2, 20);
B: transferMoney(acc2, acc1 ,25);

It is possible that thread A has acquired a lock on the acc1 object and is waiting to acquire a lock on the acc2 object. Meanwhile, thread B has acquired a lock on the acc2 object and is waiting for a lock on acc1. This will lead to deadlock, and the system would have to be restarted! There is, however, a way to avoid this, which is called "lock ordering." Personally, I find this a bit complex. 

A cleaner approach is implemented by ReentrantLock with the use of tryLock() method. This approach is called the "timed and polled lock-acquisition." It lets you regain control if you cannot acquire all the required locks, release the ones you have acquired and retry. 

So, using tryLock, we will attempt to acquire both locks. If we cannot attain both, we will release if one of these has been acquired, then retry

public boolean transferMoneyWithTryLock(Account fromAccount,
   Account toAccount, float amount) throws InsufficientAmountException, InterruptedException 
{
 // we are defining a stopTime
 long stopTime = System.nanoTime() + 5000;
 while (true) {
  if (fromAccount.lock.tryLock()) {
    try {
   if (toAccount.lock.tryLock()) {
       try {
      if (amount > fromAccount.getCurrentAmount()) {
     throw new InsufficientAmountException(          "Insufficient Balance");
       } else {
     fromAccount.debit(amount);
     toAccount.credit(amount);
       }
    } finally {
       toAccount.lock.unlock();
    }
    }
      } finally {
   fromAccount.lock.unlock();
      }
  }
 if(System.nanoTime() < stopTime)
    return false;
    Thread.sleep(100);
 }//while
 }

Here we implemented a timed lock, so if the locks cannot be acquired within the specified time, the transferMoney method will return a failure notice and exit gracefully. We can also maintain time budget activities using this concept. 


3. Interruptible Lock Acquisition:

Interruptible lock acquisition allows locking to be used within cancellable activities.
The lockInterruptibly method allows us to try and acquire a lock while being available for interruption. So, basically it allows the thread to immediately react to the interrupt signal sent to it from another thread. 

This can be helpful when we want to send a KILL signal to all the waiting locks. Let's see one example: Suppose we have a shared line to send messages. We would want to design it in such a way that if another thread comes and interrupts the current thread, the lock should release and perform the exit or shut down operations to cancel the current task.

public boolean sendOnSharedLine(String message) throws InterruptedException{
  lock.lockInterruptibly();
  try{
   return cancellableSendOnSharedLine(message);
  } finally {
   lock.unlock();
  }
 }
private boolean cancellableSendOnSharedLine(String message){
.......

4. Non-block Structured Locking:

In intrinsic locks, acquire-release pairs are block-structured. In other words, a lock is always released in the same basic block in which it was acquired, regardless of how control exits the block. Extrinsic locks allow the facility to have more explicit control. Some concepts, like Lock Strapping, can be achieved more easily using extrinsic locks. Some use cases are seen in hash-bashed collections and linked lists.

private ReentrantLock lock;
public void foo() {
  ...
  lock.lock();
  ...
}
public void bar() {
  ...
  lock.unlock();
  ...
}

Intrinsic locks and extrinsic locks have the same mechanism inside for locking, so the performance improvement is purely subjective. It depends on the use cases we discussed above. Extrinsic locks give a more explicit control mechanism for better handling of deadlocks, starvation, and so on

When should you use ReentrantLocks? 

The answer is pretty simple - use it when you actually need something it provides that synchronized doesn't, like timed lock waits, interruptible lock waits, non-block-structured locks, multiple condition variables, or lock polling. ReentrantLock also has scalability benefits, and you should use it if you actually have a situation that exhibits high contention, but remember that the vast majority of synchronized blocks hardly ever exhibit any contention, let alone high contention. I would advise developing with synchronization until synchronization has proven to be inadequate, rather than simply assuming "the performance will be better" if you use ReentrantLock.

Remember, these are advanced tools for advanced users. (And truly advanced users tend to prefer the simplest tools they can find until they're convinced the simple tools are inadequate.) As always, make it right first, and then worry about whether or not you have to make it faster.


Friday, October 10, 2014

Java Basics: String Pool & String Handling in Java

In today's post we will  go through various ways of creating strings and understanding memory management of strings.

Java provides two ways of creating strings: using string literal or with new operator. So next question comes in mind is: why there are two different ways and what is the advantage of the same.

Before we go into more details, let's first understand internal memory management of String objects.

JVM maintains string pool to maintain all string variaobles in the memory. String pools are generally stored in the PermGen area of Heap memory since they are constants and will be required for longer period. So when you create string variable using literals, jvm first checks if variable already exists in the string pool. If it does then only reference of the object will be assigned to new string variable whereas when strings are created using new operator they are treated as any other java objects and will be stored in the heap memory.

So let's understand this concepts using below example,

   static String iAmReference = "i am reference"; 
   static String iAmSameReference = "i am reference"; 

Here, first variable, iAmReference will be created as new object since string doesn't exist in the string pool yet. Now, when we try to create iAmSameReference , jvm checks string pool and finds there is one object already created (iAmReference) and so will assign the reference of the same object to iAmSameReference.

if(iAmReference == iAmSameReference){
  System.out.println("References are always same"); 
}

Output: References are always same

Now, lets see what happens in case of new operator.

    static String iAmNewObject1 = new String("i am reference");
    static String iAmNewObject2 = new String("i am reference");

Here, both objects are created in the heap memory, no different than any other objects. To verify what we just discussed, try to execute below statements.

//compare reference with object.
if(!(iAmReference == iAmNewObject1)){
   System.out.println("Objects and reference are never same"); 
}
//compare objects created in heap memory.
if(!(iAmNewObject1 == iAmNewObject2)){
   System.out.println("Two objects are never same in java. Remember hash code ??"); 
}

Output: 
Objects and reference are never same.
Two objects are never same in java. Remember hash code ??

Now, what if you want both objects, iAmNewObject1 and iAmNewObject2, to put in string pool ?
Java provides method called intern() which provides this facility. So now let's put both of these objects in the string pool to save memory and avoid duplication of objects.

iAmNewObject1 = iAmNewObject1.intern();
iAmNewObject2 = iAmNewObject2.intern();

You can verify if objects are now created in the string pool or not by executing below statements:

if(iAmReference == iAmNewObject1){
   System.out.println("Now iAmNewObject1 is put on String pool from heap memory."); 
}

if(iAmNewObject1 == iAmNewObject2){
   System.out.println("Now iAmNewObject2 is also put on String pool from heap memory."); 
}
Output: 
Now iAmNewObject1 is put on String pool from heap memory.
Now iAmNewObject2 is also put on String pool from heap memory.

Hope, this will help you clear your doubts about java string handling.

Working Code can be found here.


Wednesday, October 8, 2014

Java Thread I: Thread Exception Handling with Example

This post will explain simple example of exception handling in java threads.

Have you ever wondered what happens when multiple threads are accessing shared data and one of them throws exception and you don't even know which thread did it and what to do next !!

What happens if one of the Strings is null and we get a NullPointerException? What happens if we run out of memory and get an OutOfMemoryError? What happens if we get an OOME and at the same time the connection does not work anymore? Then the finally would cause an exception, which would mask the OOME, and make it disappear. There are lots of possibilities, and if we try to cater for all eventualities (excuse the pun) then we will go crazy trying and our code will look rather complicated.

See below piece of code and try to see what could be the output here,

public static void main(String[] args) {
Thread t1 = new Thread(new MyThreadExceptionHandling());
Thread t2 = new Thread(new MyThreadExceptionHandling());
t1.start();
t2.start();
new RuntimeException(); 
}

@Override
public void run(){
System.out.println("Creating thread");
int i = 1/0;
}

Output:
Creating thread
Creating thread
Exception in thread "Thread-1" java.lang.ArithmeticException: / by zero
at com.practice.java.threads.ThreadExceptionHandling.run(ThreadExceptionHandling.java:36)
at java.lang.Thread.run(Thread.java:619)
Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero
at com.practice.java.threads.ThreadExceptionHandling.run(ThreadExceptionHandling.java:36)
at java.lang.Thread.run(Thread.java:619)

So in the real world, how are exceptions handled? Frequently, exceptions are stubbed out and ignored, because the writer of the code did not know how to handle the error (and was going to go back and fix it, one day, but the project manager was breathing down his neck and the release had to go out that afternoon). This is bad, since you then do not know that something has gone awry. On the other hand, if the exception bubbles up the call stack, it may kill the thread, and you may never know that there was an exception.

I have witnessed production code do things like this (I kid you not):


    try {

      // do something
    } catch(Exception ex) {
      // log to some obscure log file, maybe
      return "";
    }
  
The effect was that the webpage showed empty strings as values when something went wrong with the code.

My approach to exceptions is to have a central mechanism that deals with any exceptions that I am not 100% sure of how to handle. Whenever something goes wrong, this central place is notified. However, what happens when you are using someone else's code and their threads die without warning?


Java came up with uncaught exception handlers (Thread.UncaughtExceptionHandler) from jdk 1.5 onwards.


According to the Java API documentation, when a thread is about to terminate due to an uncaught exception, the Java Virtual Machine will query the thread for its UncaughtExceptionHandler using Thread.getUncaughtExceptionHandler() and will invoke the handler's uncaughtException method, passing the thread and the exception as arguments. If a thread has not had its UncaughtExceptionHandler explicitly set, then its ThreadGroup object acts as its UncaughtExceptionHandler. If the ThreadGroup object has no special requirements for dealing with the exception, it can forward the invocation to the default uncaught exception handler.


Java allows you to install a default exception handler for threads, for just this very reason. You have three options in doing so:

  • You can set it for a specific Thread  (custom handler for thread t)
  • You can set it for a ThreadGroup (which means for all Threads in that group)
  • You can set it VM wide for all Threads regardless (default handler)
In our example, where the Exception occurs in code we cannot change, we'll need to go with option 3. Doing so is very easy, and allows us to log the Exception that has occurred, get the full stack trace, and then restart the worker Thread since it will have terminated by the time the exception handler is notified. Here is the code modified to install a default exception handler (only the modified code is shown):

private class MyThreadExceptionHandler implements UncaughtExceptionHandler{

@Override

public void uncaughtException(Thread t, Throwable e) {
                   StringWriter sw = new StringWriter();
                   e.printStackTrace(new PrintWriter(sw));
                   String stacktrace = sw.toString();

System.out.println("ERROR! An exception occurred in " + t.getName() + ". Cause: " + e.getMessage());

                        System.out.println(stacktrace);
sendMail(stacktrace); //send mail to interested parties or stack holders.

}
}

Now, change the main() method as below:

public static void main(String[] args) {

Thread t1 = new Thread(new ThreadExceptionHandling());
Thread t2 = new Thread(new ThreadExceptionHandling());
Thread.UncaughtExceptionHandler exception = new ThreadExceptionHandling(). new MyThreadExceptionHandler();
      
// Add the handler to the thread object
Thread.setDefaultUncaughtExceptionHandler(exception);
// t1.setUncaughtExceptionHandler(custoException1);
// t2.setUncaughtExceptionHandler(customException2);
t1.start();
t2.start();
new RuntimeException(); //main class is also a thread and it doesnt have any exception handler.
}

Now, try to run the program and check the output. It makes life a lot easier since you don't have to break your head thinking of all possible failure scenarios upfront and make your code complex in handling them..................................

Working code for above example can be found here.