千家信息网

java高并发中如何进行线程封闭

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,这篇文章给大家介绍java高并发中如何进行线程封闭,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。很多时候都想躲避并发,避免并发除了设计成不可变对象其实还有一个简单的方法就是线程封
千家信息网最后更新 2025年12月02日java高并发中如何进行线程封闭

这篇文章给大家介绍java高并发中如何进行线程封闭,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

很多时候都想躲避并发,避免并发除了设计成不可变对象其实还有一个简单的方法就是线程封闭。

什么是线程封闭?

其实就是把对象封装到一个线程里,只有这一个线程能看到这个对象。那么这个对象就算不是线程安全的,也不会出现线程安全方面的问题了,因为他只能在一个线程里面进行访问。那么如何实现线程封闭呢?

如何实现线程封闭?

  • Ad-hoc 线程封闭:程序控制实现,最糟糕,忽略

  • 堆栈封闭:局部变量,无并发问题。是我们现实中使用最多的封闭了,简单说就是局部变量。多个线程访问一个方法的时候,方法中的局部变量都会被拷贝一份到线程栈中,所以局部变量是不会被线程共享的,因此不会出现并发问题。所以全局变量容易引起并发问题。

  • ThreadLocal线程封闭:特别好的封闭方法。ThreadLocal内部维护了一个map,key是线程的名称,value就是封闭的对象。

ThreadLocal

正常来讲我们每一个请求对服务器来讲都是一个线程在运行,我们希望线程间隔离,一个线程在被后端服务器实际处理的时候,可以通过Filter过滤器取出当前的用户,然后将数据存放在ThreadLocal中,当线程被接口的service以及其他相关类进行处理的时候很可能需要在取出当前用户,这时就可以随时随地从ThreadLocal中直接拿到之前存储的值这样用起来就很方便了。如果我们不这样做,会有什么麻烦呢?因为我们的登录用户通常是从request中取出来的,因此需要带上request或者从request中取出来的用户信息,从controller层开始不停的往下传,甚至会传到一些util类中,这样会使得代码看起来很臃肿。当使用ThreadLocal和Filter,就可以很方便的在接口处理之前,前取出相关的信息,在接口实际处理的时候,什么时候需要什么时候再把信息取出来,这样代码在设计的时候就容易多了,不至于把request从controller一直传递下去。

具体使用实例如下:

新建一个类:

public class RequestHolder {    //因为当前没有登录用户,我们用线程id来充当    private final static ThreadLocal requestHolder = new ThreadLocal<>();    /**     * 请求进入到后端服务器,但是还没有实际处理的时候调用add,可以使用Filter     * @param id     */    public static void add(Long id) {        //虽然只传入id,但是threadLocal会取出当前线程id放到map中的key,value是传入的值        requestHolder.set(id);    }    public static Long getId() {        return requestHolder.get();    }    /**     * 如果不做remove的话,会造成内存泄漏,数据永远不会释放掉     * 需要在接口真正处理完成之后进行调用,可以使用interceptor     */    public static void remove() {        requestHolder.remove();    }}

这个类就用来存放ThreadLocal。

新建一个Filter:

@Slf4jpublic class HttpFilter implements Filter {    @Override    public void init(FilterConfig filterConfig) throws ServletException {    }    @Override    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {        HttpServletRequest httpServletRequest = (HttpServletRequest) request;//        httpServletRequest.getSession().getAttribute("user");        log.info("do filter , {}, {}", Thread.currentThread().getId(), ((HttpServletRequest) request).getServletPath());        RequestHolder.add(Thread.currentThread().getId());        // 如果这个Filter不想拦截住这个请求,只想做单独的数据处理时,要调用chain.doFilter,使得拦截器处理完        chain.doFilter(request, response);    }    @Override    public void destroy() {    }}

新建一个Interceptor:

@Slf4jpublic class HttpInterceptor extends HandlerInterceptorAdapter {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        log.info("preHandle");        return true;    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {        RequestHolder.remove();        log.info("afterCompletion");        return ;    }}

配置filter和interceptor:

@Configurationpublic class Config implements WebMvcConfigurer {    @Bean    public FilterRegistrationBean httpFilter(){        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>();        // 设置filter        filterRegistrationBean.setFilter(new HttpFilter());        // 拦截规则        filterRegistrationBean.addUrlPatterns("/threadLocal/*");        return filterRegistrationBean;    }    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/**");    }}

新建一个controller进行测试:

@RestController@RequestMapping("threadLocal")public class ThreadLocalController {    @GetMapping("/test")    public Long test() {        return RequestHolder.getId();    }}

在浏览器中输入localhost:8080/threadLocal/test可以输出线程的id,与后台的输出id一致。

关于java高并发中如何进行线程封闭就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

线程 时候 处理 变量 对象 用户 就是 局部 接口 方法 问题 信息 实际 数据 服务器 服务 安全 代码 内容 更多 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 民营企业档案专题数据库 dns服务器上网速度快 久大网络技术有限公司有哪些 湖北通信软件开发推广 关系数据库的规范化 辛集市网络安全招标公告 2021国家网络安全宣传周是 数据库操作日志表内容 厌余年手游服务器维护公告 腾讯云服务器竞价实例怎么样 pp查重数据库 access数据库图片怎么放 数据库怎么清楚数据表 医美管理软件开发背景 永劫无间服务器会增加吗 泰拉瑞亚手机版服务器怎么开呀 新媒体专业学手机软件开发吗 大数据软件开发人 2022年网络安全知识考试答案 河南星瑞网络技术有限公司 安卓系统是哪个软件开发的 清远软件开发怎么样 广州企业软件开发要多少钱 河北外协加工软件开发教程 数据库如何运行语句 免费电脑版服务器我的世界 挖财网络技术有限公司待遇 网页与数据库的连接 数据库建立好了如何建立数据文件 网络安全法数据分类
0