关于类java.lang.ThreadLocal的javadoc让我感到困惑.他们说每个访问线程局部变量的线程都有自己独立初始化的变量副本.下面是一个示例(不是真实的生活示例),它证明了线程局部变量中保存的变量可以被许多线程共享:
package com.mohamad.test.threadlocal;
import java.util.List;
public class ThreadLocalExample {
private static final ThreadLocal<List<Integer>> myThreadLocal = new ThreadLocal<List<Integer>>();
public static List<Integer> get() {
return (myThreadLocal.get());
}
public static void set(List<Integer> value) {
myThreadLocal.set(value);
}
}
package com.mohamad.test.threadlocal;
import java.util.ArrayList;
import java.util.List;
public class TestThreadLocal implements Runnable {
private static List<Integer> MY_TEST_LIST = new ArrayList<Integer>(){
/** The serialVersionUID */
private static final long serialVersionUID = -2419885728976816054L;
{add(1);}
};
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
ThreadLocalExample.set(MY_TEST_LIST);
List<Integer> integers = …Run Code Online (Sandbox Code Playgroud) 对于我的应用程序,我必须将某些信息携带到应用程序的每一层(一个示例可能是为传入请求生成的唯一事务ID).
所以,我打算创建一个引用的类ThreadLocal<ConcurrentMap<String, Object>>.
感谢有人可以提供帮助; 我有一个混乱,出于以下方法,哪一个更好:
1. AppContext.java有静态方法
public final class AppContext {
private static final ThreadLocal<ConcurrentMap<String, Object>> context = new ThreadLocal<>();
public static void set(final String key, final Object value) {
// set key value in thread local
}
public static Object get(final String key) {
// get value from thread local
}
}
Run Code Online (Sandbox Code Playgroud)
2.具有非静态方法的AppContext.java
public final class AppContext {
private static final ThreadLocal<ConcurrentMap<String, Object>> context = new ThreadLocal<>();
public void set(final String key, final Object value) { …Run Code Online (Sandbox Code Playgroud) 在 django 中,持久的数据库连接由threading.local. 此代码驻留在类中django.db.utils.ConnectionHandler。由于此类在django.db.__init.__.py其中实例化,因此当我们执行import django.db. 这会在请求/响应周期中的某个地方发生。对于同一线程甚至同一进程中的不同线程中的后续请求,django.db.__init__.py将不会执行,因为它已经加载。
所以我的问题是它不会共享同一进程中所有线程的连接。我在这里错过了什么吗?
我认为像下面这样的东西应该可以正常工作
# file db/__init__.py
connections = threading.local()
connections.connections = ConnectionHandler()
Run Code Online (Sandbox Code Playgroud) 我目前Threadlocal用于保存当前用户的 ID,以便根据每个用户的 Web 请求在整个应用程序中使用。我无权访问HttpContext较低环境中的 ,但想访问静态 UserId 而不将其作为参数传递到任何地方。最近,我一直在通过添加并行操作async/await.这不再能保证我在每个操作中都有正确的值Task.
我研究,发现AsyncLocal在.Net 4.6,但我目前只限于.Net 4.5.1。作为替代方案,是否CallContext.LogicalGet/SetData()能够实现我想要的?
我对threadLocal的initialValue和withInital方法有点困惑。
考虑一种情况,我在父线程中有数据,并且我正在使用InheritableThreadLocal.
public class Parent extends Thread {
public static ThreadLocal<String> data = new InheritableThreadLocal<String>() {
@Override
protected String initialValue() {
return "temp";
}
};
public static void main(String[] args) {
new Parent().start();
}
public void run() {
data.set("parent data");
System.out.println("Parent Thread Value :" + data.get());
new ChildThread().start();
}
class ChildThread extends Thread {
public void run() {
System.out.println("Child Thread Value :" + Parent.data.get());
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Parent Thread Value : parent data …Run Code Online (Sandbox Code Playgroud) java multithreading thread-local java-8 inheritable-thread-local
天真地,我期望ThreadLocal是某种类型的Thread的WeakHashMap.当我得知ThreadLocal的值实际上保存在Thread中的一个映射中时,我有点困惑.为什么这样做?我希望如果值保存在ThreadLocal本身中,那么与ThreadLocal相关的资源泄漏就不会存在.
澄清:我在考虑类似的事情
public class AlternativeThreadLocal<T> {
private final Map<Thread, T> values =
Collections.synchronizedMap(new WeakHashMap<Thread, T>());
public void set(T value) { values.put(Thread.currentThread(), value); }
public T get() { return values.get(Thread.currentThread());}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,这可以防止一个奇怪的问题,即如果值以某种方式强烈引用ThreadLocal本身,那么ThreadLocal和它遗留的值都不会被垃圾收集,直到Thread死掉.(当ThreadLocal是值引用的类上的静态变量时,可能会出现最狡猾的形式.现在,在应用程序服务器的重新部署中存在大量资源泄漏,因为无法收集对象及其类.)
看了这个问题之后,我想我想要包装ThreadLocal来添加重置行为.
我想要一个类似于ThreadLocal的东西,我可以从任何线程调用一个方法将所有值设置回相同的值.到目前为止我有这个:
public class ThreadLocalFlag {
private ThreadLocal<Boolean> flag;
private List<Boolean> allValues = new ArrayList<Boolean>();
public ThreadLocalFlag() {
flag = new ThreadLocal<Boolean>() {
@Override protected Boolean initialValue() {
Boolean value = false;
allValues.add(value);
return value;
}
};
}
public boolean get() {
return flag.get();
}
public void set(Boolean value) {
flag.set(value);
}
public void setAll(Boolean value) {
for (Boolean tlValue : allValues) {
tlValue = value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我担心原语的自动装箱可能意味着我存储在列表中的副本将不会引用ThreadLocal引用的相同变量(如果我尝试设置它们).我还没有测试过这段代码,并且在我继续沿着这条路走下去之前,我正在寻找一些专家建议.
有人会问"你为什么这样做?".我正在一个框架中工作,其他线程回调到我的代码中,我没有对它们的引用.我想定期更新他们使用的ThreadLocal变量中的值,因此执行该更新需要使用该变量的线程进行更新.我只需要一种方法来通知所有这些线程他们的ThreadLocal变量是陈旧的.
我很高兴最近对这个三年前的问题有了新的批评,尽管我觉得它的语气比专业还要小.我提供的解决方案在此期间没有发生任何事故.然而,必然有更好的方法来实现提出这个问题的目标,我邀请评论家提供明显更好的答案.为此,我将尝试更清楚地解决我试图解决的问题.
正如我之前提到的,我正在使用一个框架,其中多个线程正在使用我的代码,在我的控制之外.该框架是QuickFIX/J,我正在实现Application接口.该接口定义了用于处理FIX消息的钩子,在我的使用中,框架被配置为多线程,因此可以同时处理与应用程序的每个FIX连接.
但是,QuickFIX/J框架仅为所有线程使用该接口的单个实例实例.我无法控制线程如何启动,并且每个都在为不同的连接提供不同的配置细节和其他状态.很自然地让一些经常访问但很少更新的状态存在于ThreadLocal框架启动线程后加载其初始值的各种s中. …
我一直在使用ThreadLocal在一端设置值,并使用另一端的get方法检索值,下面的代码是
public class sample()
{
public ThreadLocal<Object> tl1 = new ThreadLocal<Object>();
protected void Page_Load(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(Myfunction));
setname("myval");
thread.Start();
}
public void setname(String name)
{
tl1.Value = name;
}
public String getname()
{
return (String)tl1.Value;
}
public void Myfunction()
{
String value=getname();
}
}
Run Code Online (Sandbox Code Playgroud)
我这已经在setname方法中正确设置了值.
但它发生的是当我试图在单独的线程中获取其值时,即使设置值名称也更改为null.
ex: "myval" changed to "null"
Run Code Online (Sandbox Code Playgroud)
我怎么解决这个问题
[IMG] http://i60.tinypic.com/121bww0.jpg [/IMG] (请求高代表用户,请链接图片,它会支持这个问题.)
嗨,图像描绘了我理解的网络应用程序流程.浏览器向spring调度程序servlet发送请求.servlet为每个请求生成一个新线程(我假设默认情况下这样做.我不知道如何控制它.)代码如下:
public class Result{
private List<String> response = new ArrayList<String>();
public setResponse(List<String> list){
this.response = list;
}
public list<String> getResponse(){
return response ;
}
}
public class ResponseUtil {
private static final ThreadLocal<Result> responseObject = new InheritableThreadLocal<Result>();
public static void initialize(){
if(responseObject.get() == null){
Result result= new Result();
result.setResponse(new ArrayList<String>());
responseObject.set(result);
}
}
public static void addMessage(String message){
List<String> messages = responseObject.get().getResponse();
messages.add(message);
}
public static Response getResponse(){
return responseObject.get();
}
}
@Component
public class OnboardingEndPointImpl …Run Code Online (Sandbox Code Playgroud) 让我们从一段代码(Coliru)开始:
#include <iostream>
#include <thread>
using namespace std;
struct A
{
thread_local static A* p_a;
thread_local static int i;
};
thread_local int A::i;
thread_local A* A::p_a;
int main( )
{
A::p_a = new A;
auto lambda = [](A* a)
{
a->i = 1; // Prints 1 (below, of course)
std::cout << a->i << std::endl;
};
std::thread t(std::bind(lambda, A::p_a));
t.join();
// Prints 0 (it hasn't been modified)
std::cout << A::p_a->i << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
正如你们所看到的,第二个线程修改了它的线程本地副本A::i,即使我从另一个线程的另一个线程本地对象访问它.这是预期的行为吗?因为除非我将指针或引用传递给我想要读取的外部thread_local对象,否则无法使用"referer"从另一个线程获取信息.
使用"referer",我引用了一些管理或者可以让你从其线程访问自己的thread_local变量的东西.但那是不可能的!任何产生thread_local变量的表达式,无论是谁(我已经完成了不同的测试,甚至是访问器函数),都使用读取线程的thread_local实例结束.
thread-local ×10
java ×6
c# ×2
.net ×1
async-await ×1
c++ ×1
c++11 ×1
django ×1
django-orm ×1
httprequest ×1
java-8 ×1
servlets ×1
spring ×1