This article assumes that you are already familiar with concurrent programming and design. Java 1.5 introduced the concurrent library java.util.concurrent
, which provides an extensive set of classes for dealing with concurrency issues, these sit alongside some existing classes that have been around since earlier times. I've noticed that some of the classes I mention here don't get used as often as they should, especially given that they are quick wins. This article only scratches the surface of the new classes available, but should provide a starting point for further reading.
Note that if you have many, many threads which are shortlived, this may be of limited use.
There are many cases where synchronization can be avoided by using ThreadLocal
. These cases are usually where an object that is heavy to create such as SimpleDateFormat
needs to be cached for later use, but the code in question is multi-threaded and therefore would cause multi-threaded access to the variable.
java.lang.ThreadLocal
does exactly this, as it is a wrapper object, that ensures each thread gets its own copy of the variable being protected. See the example below:
package com.thecoderscorner.example;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Concurrent
{
private ThreadLocal<DateFormat> sdf = new ThreadLocal<DateFormat>() {
protected DateFormat initialValue()
{
return new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
}
};
public String someOperation()
{
return "important text created at " + sdf.get().format(new Date());
}
public static void main(String[] args)
{
Concurrent con = new Concurrent();
System.out.println(con.someOperation());
}
}
and standard out was
important text created at 20131023T22:34:00 Process finished with exit code 0
In the example above we create an anonymous class that extends ThreadLocal
, in the simplest case, you override the initialValue(..)
method. Consider initialValue
like a constructor that gets called the first time a thread access the variable. In order to access the stored variable call get(..)
, which returns the correct type, as it is a Java 1.5 generic class.
It really is that simple, and can avoid costly synchronization when a per thread variable is all that's required. Next step, concurrent maps.