gpt4 book ai didi

java - 使用 ThreadLocal 的最佳方法是什么 - 通过静态或非静态方法?

转载 作者:行者123 更新时间:2023-12-02 10:58:55 34 4
gpt4 key购买 nike

对于我的应用程序,我必须将某些信息传递到应用程序的每一层(一个示例可能是为传入请求生成的唯一事务 ID)。

因此,我计划创建一个引用 ThreadLocal<ConcurrentMap<String, Object>> 的类。

感谢有人可以提供帮助;我对以下方法感到困惑,哪种方法更好:

<强>1。 AppContext.java 具有静态方法

public final class AppContext {
private static final ThreadLocal&lt;ConcurrentMap&lt;String, Object&gt;&gt; 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
}
}

<强>2。 AppContext.java 具有非静态方法

public final class AppContext {
private static final ThreadLocal&lt;ConcurrentMap&lt;String, Object&gt;&gt; context = new ThreadLocal<>();

public void set(final String key, final Object value) {
// set key value in thread local
}

public Object get(final String key) {
// get value from thread local
}
}

最佳答案

尽管其他人可能会说,ThreadLocal 变量本质上并不是邪恶的,只是在使用时需要额外的小心和理解。线程安全性并不真正相关,因为它们本质上与一个线程相关。当这些线程可能被应用程序的其他不同用户重用时,就会出现问题。在基于 Java 的 Web 应用程序中,情况就是如此;然而,您一次只能指望一个用户/请求存在于该线程上。极其重要的步骤是确保在每个请求结束时清理 ThreadLocal 对象。

因此,为了避免不必要地为每个请求实例化新的上下文,我建议创建多个静态类型安全的 ThreadLocal 对象,所有对象都位于“上下文”类中,其中这些对象以某种方式相关。您可以使用多个上下文类来组织这些上下文项的各个组。

但是,本着 ThreadLocal 批评者的精神,我同意应该谨慎使用 ThreadLocal,过度使用可能会产生代码异味。

以下是上述方法的示例。

“上下文”类。

public class LogContext {

private static ThreadLocal<String> localCorrelationId = new ThreadLocal<String>();
private static ThreadLocal<String> localUserId = new ThreadLocal<String>();

public static String getCorrelationId() {
return localCorrelationId.get();
}

public static void setCorrelationId(String correlationId) {
localCorrelationId.set(correlationId);
}

public static String getUserId() {
return localUserId.get();
}

public static void setUserId(String userId) {
localUserId.set(userId);
}

public static void cleanup() {
localCorrelationId.remove();
localUserId.remove();
}
}

通过 Servlet 过滤器管理上下文

@WebFilter(filterName = "LogContextFilter", urlPatterns = {"/*"})
public class LogContextFilter implements Filter {

public void init(FilterConfig filterConfig) {

}

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {

try {
LogContext.setCorrelationId(UUID.randomUUID().toString());
chain.doFilter(request, response);
} catch (Throwable t) {
t.printStackTrace();
} finally {
//This is critical!
LogContext.cleanup();
}

}

public void destroy() {

}

}

访问上下文(例如从 Servlet)

@WebServlet(name = "SimpleServlet", urlPatterns = {"/SimpleServlet"})
public class SimpleServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

String correlationId = LogContext.getCorrelationId();
}

}

关于java - 使用 ThreadLocal 的最佳方法是什么 - 通过静态或非静态方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22185956/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com