I am not sure if I get this abous ThreadLocals. Sometimes you can read that a common practice is to make JDBC connections as ThreadLocals so each thread gets its own copy of the connection. Let´s assume the socket below is a JDBC connection. Then I do:
public ThreadLocalSocket() throws IOException {
Runnable runnable = new Runnable() {
ThreadLocal<Socket> threadLocal = new ThreadLocal<>();
@Override
public void run() {
try {
threadLocal.set(new Socket("www.google.com", 80));
} catch (IOException e) {e.printStackTrace();}
Thread thread = Thread.currentThread();
for (int j = 0; j < 10 ; j++) {
Socket sock = threadLocal.get();
if (thread.getName().equals("t1")) {
if (!sock.isClosed()) {
try {
sock.close();
} catch (IOException e) {e.printStackTrace();}
}
}
System.out.println("Thread: " + thread.getName()+ ", is closed? " + sock.isClosed() + ", sock hashCode = " + sock.hashCode());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {e.printStackTrace();}
}
}
};
Thread t1 = new Thread(runnable);
t1.setName("t1");
Thread t2 = new Thread(runnable);
t2.setName("t2");
t1.start();
t2.start();
}
Why cannot I simply do this without ThreadLocals? The behaviour is exactly the same in the following code snippet as the code example above:
public ThreadLocalSocket() throws IOException {
Runnable runnable = new Runnable() {
@Override
public void run() {
Socket socket = null;
try {
socket = new Socket("www.google.com", 80);
} catch (IOException e) {e.printStackTrace();}
Thread thread = Thread.currentThread();
for (int j = 0; j < 10 ; j++) {
if (thread.getName().equals("t1")) {
if (!socket.isClosed()) {
try {
socket.close();
} catch (IOException e) {e.printStackTrace();}
}
}
System.out.println("Thread: " + thread.getName()+ ", is closed? " + socket.isClosed() + ", socket hashCode = " + socket.hashCode());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {e.printStackTrace();}
}
}
};
Thread t1 = new Thread(runnable);
t1.setName("t1");
Thread t2 = new Thread(runnable);
t2.setName("t2");
t1.start();
t2.start();
}
Yes, in your use case, it's pretty useless.
The javadoc of ThreadLocal
states
ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
The typical use case is to have the ThreadLocal
as a kind of global member so that you don't have to pass around the referenced value. You expose it through some static
methods and every piece of code you write has access to it without having to have it injected every time.
For example, Spring MVC provides the class RequestContextHolder
which keeps a ThreadLocal
reference to a ServletRequest
object. Since servlet containers typically (ie. not async mode) work by handling the request in a single thread, and instead of having to pass around the ServletRequest
to every single component in the handling flow, Spring sets it once in the RequestContextHolder
and other components have access to it through static
helper methods (really just the attributes of the request).