Monday, August 3, 2009

per-thread Singleton and per-thread Logging in Java


Usage of ThreadLocal: per-thread Singleton and per-thread Logging

Should you require a refresh of what ThreadLocals in Java are and how they work, refer to this article first. You can then proceed with the current article for understanding two of the most common uses of ThreadLocals in Java.


per-thread Singleton impl using ThreadLocal


Suppose you have a need of having a JDBC Connection objects per thread of your application. The moment you hear the term 'per-thread', ThreadLocal automatically comes into mind as that's what it's primarily meant for. Below is a sample implementation of how easily can you actually use ThreadLocal for a per-thread JDBC Connection object in Java.



public class ConnectionDispenser {

private static class ThreadLocalConnection extends ThreadLocal {

public Object initialValue() {

return DriverManager.getConnection(ConfigurationSingleton.getDbUrl());

}

}

private static ThreadLocalConnection conn = new ThreadLocalConnection();

public static Connection getConnection() {

return (Connection) conn.get();

}

}


Most of the code is self-explanatory and you can easily see how overriding the 'initialValue()' method of ThreadLocal is doing the trick of getting a Connection object by calling 'getConnection' method of the 'DriverManager' class. As you know the 'initialValue()' method is called only once for a ThreadLocal object and hence the Connection object will be obtained only once per thread (as a ThreadLocal object is created per thread only). From then on, whenever the particular thread requires the Connection object it simply calls the static 'getConnection' method of the your 'ConnectionDispenser' class, which in turn calls the 'get()' method of ThreadLocal to fetch the Connection object associated with that particular thread.

per-thread Debug Logging impl using ThreadLocal


Ever thought of having a per-thread DEBUG logging for any of your applications? Few multi-threading applications do get trickier at times and having per-thread DEBUG logs might be of great help in such situations as you probably can't visualize the actual order in which the threads might have executed and changed the shared objects. Here goes a sample implementation of per-thread DEBUG logging in Java using ThreadLocal.



public class DebugLogger {

private static class ThreadLocalList extends ThreadLocal {

public Object initialValue() {

return new ArrayList();

}

public List getList() {

return (List) super.get();

}

}


private ThreadLocalList list = new ThreadLocalList();

private static String[] stringArray = new String[0];


public void clear() {

list.getList().clear();

}


public void put(String text) {

list.getList().add(text);

}


public String[] get() {

return list.getList().toArray(stringArray);

}

}


As you can identify we are using an ArrayList object to store the logging info for a thread. 'initialValue' has been overridden to initialize every thread with a new ArrayList object. Whenever your multi-threaded application calls the 'put' method of your 'DebugLogger' class then all that method does is that it adds the logging info (passed as an String parameter to the 'put' call) to the corresponding ArrayList object of the current thread. Similarly a 'get' call of your 'DebugLogger' class simply returns the associated ArrayList object of the current thread in form of an String array. Evidently the 'clear' method of your 'DebugLogger' class is for clearing the logging info captured so far for the current thread - it'll simply clear the ArrayList object holding logging info for the current thread. This might help you getting rid of the non-essential logging info, maybe based on some condition, when you know for sure that all that you need for your debugging is what you are going to capture next and now what has already been captured so far.


Source: a nice article on ThreadLocals in Java, which I thoroughly enjoyed.


Liked the article? Subscribe to this blog for regular updates. Wanna follow it to tell the world that you enjoy GeekExplains? Please find the 'Followers' widget in the rightmost sidebar.



Share/Save/Bookmark