情景:
我正在运行Jetty提供的Java Web应用程序。我在调用API时使用InheritableThreadLocal来存储一些数据,稍后当API调用进一步的操作时(在同一个线程中)访问这些数据。我存储这些数据的方式是:
代码:
public class RequestDataHolder {
protected static final InheritableThreadLocal<RequestData> reqData = new InheritableThreadLocal<RequestData>();
public static void setRequestData(RequestData request) {
reqData.set(request);
}
public static void removeRequestData() {
reqData.remove();
}
public static RequestData getRequestData() {
return (RequestData) reqData.get();
}
}
public class RequestData {
private String requestId;
private String apiStartTime;
// getters and setters
}
问题:
修改
我看到了一种行为:
当一个线程执行I / O时,是否会有一些东西,可能会继续在Jetty中管理线程的方式?由于线程重用,这里是否有可能存在父子线程?
答案 0 :(得分:0)
最后,我想出了这个问题。
<强>推理:强>
问题出现了,因为即使Java的InheritableThreadLocal保证两个线程不会看到彼此,但你放入此变量的保证不受保护在线程中可见。
示例:强>
例如,对象“RequestData”存在于堆上。现在考虑这一系列事件:
示例代码以证明推理:
public class Test implements Runnable {
@Override
public void run() {
RequestData requestData = new RequestData();
System.out.println("Thread ID: Setting requestData with hash code:" + requestData.hashCode());
RequestDataHolder.setRequestData(requestData);
Thread child = new Thread(new Runnable() {
@Override
public void run() {
RequestData requestData = RequestDataHolder.getRequestData();
System.out.println("Thread ID: Retrieved requestData with hash code:" + requestData.hashCode());
}
});
child.start();
}
public static void main(String[] args) {
Thread thread = new Thread(new Test());
thread.start();
}
}
答案 1 :(得分:0)
与Jetty示例相关的是,Jetty从先前的工作线程中生成新的工作线程 。因此,如果InheritedThreadLocal
初始化后线程1产生了线程2,则从那时起,两个线程的reqData值都相同。 InheritedThreadLocal
与Jetty结合使用似乎不安全。
此外,由于RequestDataHolder.reqData
是static final
,如果由于InheritedThreadLocal
的性质而在主线程中很早初始化了此类,则此引用将被复制到所有个子线程。