zxpnet网站 zxpnet网站
首页
前端
后端服务器
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

zxpnet

一个爱学习的java开发攻城狮
首页
前端
后端服务器
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 大后端课程视频归档
  • 南航面试题
  • 并发编程

  • 性能调优

  • java8语法

  • lombok

  • 日志

  • 工具类

  • spring

  • mybatis

  • springboot

  • redis

  • zookeeper

  • springcloud

  • dubbo

  • netty

  • springsecurity

  • mq消息中间件

  • shiro

  • beetle

  • 模板引擎

  • jpa

  • 数据结构与算法

  • 数据库知识与设计

  • gradle

  • maven

  • bus

  • 定时任务

  • docker

  • centos

  • 加解密

  • biz业务

    • 公共业务

      • 单例模式
      • Untitled
      • 接口与抽象类的应用(包括各自设计模式)
      • SpringBoot使用ApplicationEvent&Listener完成业务解耦
      • 业务异常处理
      • ThreadLocal用法
        • threadLocal作用
        • threadLocal用法
        • ThreadLocal与synchronized的区别
        • 用法1:service中拿到请求参数
        • 用法二:缓存
        • 用法三:结合aop使用
      • 自定义RequestMappingHandlerMapping实现程序版本控制
    • 商城系统

    • 许愿池

    • 微信公众号

    • 企业微信

    • 分销返利系统

  • pigx项目

  • 开源项目

  • 品达通用权限项目-黑马

  • 货币交易项目coin-尚学堂

  • php

  • backend
  • biz业务
  • 公共业务
shollin
2021-06-24
目录

ThreadLocal用法

  • threadLocal作用
  • threadLocal用法
  • ThreadLocal与synchronized的区别
  • 用法1:service中拿到请求参数
  • 用法二:缓存
  • 用法三:结合aop使用

# threadLocal作用

从Java官方文档中的描述:ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get和set方法访问)时能保证各个线程的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的,用于关联线程和线程上下文。

我们可以得知 ThreadLocal 的作用是:提供线程内的局部变量,不同的线程之间不会相互干扰,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或组件之间一些公共变量传递的复杂度。

  • 1、线程并发: 在多线程并发的场景下

  • 2、传递数据: 我们可以通过ThreadLocal在同一线程,不同组件中传递公共变量, 保存每个线程绑定的数据,在需要的地方可以直接获取, 避免参数直接传递带来的代码耦合问题

  • 3、线程隔离: 每个线程的变量都是独立的,不会互相影响, 各线程之间的数据相互隔离却又具备并发性,避免同步方式带来的性能损失

# threadLocal用法

方法声明 描述
private static ThreadLocal<类> holder = new ThreadLocal<>(); 创建ThreadLocal对象
public void set( T value) 设置当前线程绑定的局部变量
public T get() 获取当前线程绑定的局部变量
public void remove() 移除当前线程绑定的局部变量
/**
 * 请求数据的临时容器
 *
 * @author fengshuonan
 * @date 2018-05-04 11:33
 */
public class RequestDataHolder {

	// 类似 private RequestData holder = new RequestData();
    private static ThreadLocal<RequestData> holder = new ThreadLocal<>();

    public static void put(RequestData s) {
        if (holder.get() == null) {
            holder.set(s);
        }
    }

    public static RequestData get() {
        return holder.get();
    }

    public static void remove() {
        holder.remove();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# ThreadLocal与synchronized的区别

虽然ThreadLocal模式与synchronized关键字都用于处理多线程并发访问变量的问题, 不过两者处理问题的角度和思路不同。

synchronized ThreadLocal
原理 同步机制采用’以时间换空间’的方式, 只提供了一份变量,让不同的线程排队访问 ThreadLocal采用’以空间换时间’的方式, 为每一个线程都提供了一份变量的副本,从而实现同时访问而相不干扰
侧重点 多个线程之间访问资源的同步 多线程中让每个线程之间的数据相互隔离

# 用法1:service中拿到请求参数

原理:先将请求的数据封装到RequestData当中,然后交由RequestDataHolder管理,ThreadLocal将RequestData其与当前线程绑定,就可以在service中拿到数据了

因为请求都会经过controller,因此采用aop就可以解决, requestDataConverter和FastjsonConverter也都可以存RequestData

/**
 * 对控制器调用过程中,提供一种RequestData便捷调用的aop
 * <p>
 * 废弃掉了,因为requestDataConverter和FastjsonConverter都可以存RequestData
 *
 * @author fengshuonan
 * @date 2016年11月13日 下午10:15:42
 */
@Aspect
@Order(REQUEST_DATA_AOP_SORT)
public class RequestDataAop {

    @Pointcut("execution(* *..controller.*.*(..))")
    public void cutService() {
    }

    @Around("cutService()")
    public Object sessionKit(ProceedingJoinPoint point) throws Throwable {
        Object result;
        try {
            result = point.proceed();
        } finally {
            //清空 RequestDataHolder
            RequestDataHolder.remove();
        }
        return result;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
 * 快捷获取HttpServletRequest,HttpServletResponse 的工具类
 *
 * @author stylefeng
 * @Date 2018/1/4 21:24
 */
public class HttpContext {

    /**
     * 获取请求的ip地址
     *
     * @author fengshuonan
     * @Date 2018/7/23 下午3:44
     */
    public static String getIp() {
        HttpServletRequest request = HttpContext.getRequest();
        if (request == null) {
            return "127.0.0.1";
        } else {
            return request.getRemoteHost();
        }
    }

    /**
     * 获取当前请求的Request对象
     *
     * @author fengshuonan
     * @Date 2018/7/23 下午3:44
     */
    public static HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return null;
        } else {
            return requestAttributes.getRequest();
        }
    }

    /**
     * 获取当前请求的Response对象
     *
     * @author fengshuonan
     * @Date 2018/7/23 下午3:44
     */
    public static HttpServletResponse getResponse() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return null;
        } else {
            return requestAttributes.getResponse();
        }
    }

    /**
     * 获取所有请求的值
     *
     * @author fengshuonan
     * @Date 2018/7/23 下午3:44
     */
    public static Map<String, String> getRequestParameters() {
        HashMap<String, String> values = new HashMap<>();
        HttpServletRequest request = HttpContext.getRequest();
        if (request == null) {
            return values;
        }
        Enumeration enums = request.getParameterNames();
        while (enums.hasMoreElements()) {
            String paramName = (String) enums.nextElement();
            String paramValue = request.getParameter(paramName);
            values.put(paramName, paramValue);
        }
        return values;
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

# 用法二:缓存

缓存一次调用中,高频调用的属性,如用户id, 数据库连接等。

# 用法三:结合aop使用

ThreadLocal使用不当,易造成内存泄露,要及时关闭。

参考源码: RequestContextHolder

参考文章:

由浅入深,全面解析ThreadLocal_LeslieGuGu的博客-CSDN博客 (opens new window)

面试中跌倒的ThreadLocal避坑指南2:ThreadLocal用法大揭秘_哔哩哔哩_bilibili (opens new window)

黑马程序员Java基础教程由浅入深全面解析threadlocal_哔哩哔哩_bilibili (opens new window)

业务异常处理
自定义RequestMappingHandlerMapping实现程序版本控制

← 业务异常处理 自定义RequestMappingHandlerMapping实现程序版本控制→

最近更新
01
国际象棋
09-15
02
成语
09-15
03
自然拼读
09-15
更多文章>
Theme by Vdoing | Copyright © 2019-2023 zxpnet | 粤ICP备14079330号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式