Searching...
Sunday, 6 December 2015

Java ThreadLocal Usage

14:43

The Idea of ThreadLocal is every thread that accesses a ThreadLocal variable through its get/set method has its own. It is used to create thread local variables.

Here is one example once common method which is using by 2 threads and each threads modifying the value of a variable but it is not impacting to other threads. We can use synchronization for this but if we want to avoid synchronization we can use ThreadLocal Variables.

Here is one simple example which is using normal static variable and ThreadLocal variable for SimpleDateFormat.

import java.text.SimpleDateFormat;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ThreadLocalExample {

public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService ex = Executors.newFixedThreadPool(2);
MyThread1 t1 = new MyThread1();

MyThread2 t2 = new MyThread2();
for (int i = 1; i <= 2; i++) {
Future<Object> future1 = ex.submit(t1);
System.out.println(future1.get());

}
System.out.println("=====Executed MyThread1==========");
for (int i = 1; i <= 2; i++) {

Future<Object> future2 = ex.submit(t2);
System.out.println(future2.get());

}
System.out.println("=====Executed MyThread2==========");

}

}

class MyThread1 implements Callable<Object> {
private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd HHmm");
}
};

public String call() throws Exception {
System.out.println("MyThread1= " + Thread.currentThread().getName() + " got the formatter = " + formatter.get().toPattern());
formatter.set(new SimpleDateFormat());
String output = "MyThread1= " + Thread.currentThread().getName() + " set the formatter = " + formatter.get().toPattern();
return output;
}

}

class MyThread2 implements Callable<Object> {

private static SimpleDateFormat formatter = null;

public static void setFormatter(SimpleDateFormat formatter) {
MyThread2.formatter = formatter;
}

private SimpleDateFormat getFormatter() {
if (formatter == null) {
return new SimpleDateFormat("yyyyMMdd HHmm");

} else {
return formatter;
}
}

@Override
public String call() throws Exception {
System.out.println("MyThread2= " + Thread.currentThread().getName() + " got the formatter = " + getFormatter().toPattern());
setFormatter(new SimpleDateFormat());
String output = "MyThread2= " + Thread.currentThread().getName() + " set the formatter = " + getFormatter().toPattern();
return output;
}
}
Output

MyThread1= pool-1-thread-1 got the formatter = yyyyMMdd HHmm

MyThread1= pool-1-thread-1 set the formatter = M/d/yy h:mm a

MyThread1= pool-1-thread-2 got the formatter = yyyyMMdd HHmm

MyThread1= pool-1-thread-2 set the formatter = M/d/yy h:mm a

=====Executed MyThread1==========

MyThread2= pool-1-thread-1 got the formatter = yyyyMMdd HHmm

MyThread2= pool-1-thread-1 set the formatter = M/d/yy h:mm a

MyThread2= pool-1-thread-2 got the formatter = M/d/yy h:mm a

MyThread2= pool-1-thread-2 set the formatter = M/d/yy h:mm a

=====Executed MyThread2==========

 

Here MyThread1 is using the ThreadLocal and even the thread-1 changed the formatter also the thread-2 is getting the first pattern which is required for all Threads.

In the case of MyThread2 the first thread itself modifying the format and second thread is getting the modified one, so there is no ThreadLocal variable over here.

 

0 comments: