我不确定我是否得到了这个熟练的ThreadLocals。有时您可以读到,通常的做法是将JDBC连接作为ThreadLocals,以便每个线程获得自己的连接副本。我们假设下面的套接字是JDBC连接。然后我做:
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();
}
为什么我不能在没有ThreadLocals的情况下做到这一点?以下代码片段中的行为与上面的代码示例完全相同:
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();
}
答案 0 :(得分:3)
是的,在您的使用案例中,它很无用。
ThreadLocal实例通常是类中的私有静态字段 希望将状态与线程相关联(例如,用户ID或 交易ID)。
典型的用例是将ThreadLocal
作为一种全局成员,这样您就不必传递引用的值。您通过一些static
方法公开它,并且您编写的每一段代码都可以访问它,而无需每次都注入它。
例如,Spring MVC提供了类RequestContextHolder
,它对ThreadLocal
对象保持ServletRequest
引用。由于servlet容器通常(即非异步模式)通过在单个线程中处理请求来工作,而不是必须将ServletRequest
传递给处理流程中的每个组件,因此Spring在{ {1}}和其他组件可以通过RequestContextHolder
辅助方法访问它(实际上只是请求的属性)。