资讯专栏INFORMATION COLUMN

线程封闭

zero / 1805人阅读

摘要:尽量少使用全局变量变量不是常量线程封闭比较好的封闭方法维护的是一个这个是线程的名称多为我们所有封闭的值作为。在线程执行完之后将中的数据清空防止内存溢出。最后我们用测试发现打印了线程,中变量值只要是一个线程中不管在哪个类中都是共享的。

我们可以通过把对象设计成不可变对象来躲避并发,我们还可以通过使用线程封闭来实现线程安全,所谓线程封闭

就是将数据都封装到一个线程里,不让其他线程访问。

Ad-hoc 线程封闭程序控制实现,比较脆弱,尽量少用

堆栈封闭:局部变量,无并发问题,在项目中使用最多,简单说就是局部变量,方法的变量都拷贝到线程的堆栈中,只有这个线程能访问到。尽量少使用全局变量(变量不是常量)

ThreadLocal线程封闭:比较好的封闭方法

ThreadLocal维护的是一个map 这个map是线程的名称多为key 我们所有封闭的值作为value。
我们做使用Filter做登录操作都做过,我们现在来使用ThreadLoad来存储一下用户信息。
public class RequestHolder {

    private final static ThreadLocal requestHolder = new ThreadLocal<>();

    public static void add(Long id) {
        requestHolder.set(id);
    }

    public static Long getId() {
        return requestHolder.get();
    }

    public static void remove() {
        requestHolder.remove();
    }
}

声明一个ThreadLoad对象用来存储ThreadLoad信息。

@Slf4j
public class HttpFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        log.info("do filter, {}, {}", Thread.currentThread().getId(), request.getServletPath());
        RequestHolder.add(Thread.currentThread().getId());
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
@Slf4j
public 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的内容,我们在filter中将线程id加入到ThreadLoad中,然后在controller中获取,看看能不能获取的到。在线程执行完之后将ThreadLoad中的数据清空防止内存溢出。

@Controller
@RequestMapping("/threadLocal")
public class ThreadLocalController {

    @RequestMapping("/test")
    @ResponseBody
    public Long test() {
        return RequestHolder.getId();
    }
}

最后我们用postman测试发现打印了线程id,ThreadLoad中变量值只要是一个线程中不管在哪个类中都是共享的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/74486.html

相关文章

  • 「Java并发编程实战」之对象的共享

    摘要:当某个不应该发布的对象被发布时,这种情况被称为逸出。线程安全共享线程安全的对象在其内部实现同步,因此多线程可以通过对象的公有接口来进行访问而不需要进一步的同步。 前言   本系列博客是对《Java并发编程实战》的一点总结,本篇主要讲解以下几个内容,内容会比较枯燥。可能大家看标题不能能直观的感受出到底什么意思,这就是专业术语,哈哈,解释下,术语(terminology)是在特定学科领域用...

    phodal 评论0 收藏0
  • <java并发编程实战>学习三

    摘要:线程封闭当访问共享的可变数据时,通常需要使用同步。如果仅在单线程内访问数据,就不要同步。这种技术成为线程封闭。栈封闭栈封闭是线程封闭的一种特例,在栈封闭中,只能通过局部变量才能访问对象。,对象是正确创建的。 线程封闭 当访问共享的可变数据时,通常需要使用同步。一种避免使用同步的方式就是不共享数据。如果仅在单线程内访问数据,就不要同步。这种技术成为线程封闭(Thread Confine...

    Richard_Gao 评论0 收藏0
  • Java多线程&高并发

    摘要:线程启动规则对象的方法先行发生于此线程的每一个动作。所以局部变量是不被多个线程所共享的,也就不会出现并发问题。通过获取到数据,放入当前线程处理完之后将当前线程中的信息移除。主线程必须在启动其他线程后立即调用方法。 一、线程安全性 定义:当多个线程访问某个类时,不管运行时环境采用何种调度方式,或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行...

    SQC 评论0 收藏0
  • 什么时候线程不安全?怎样做到线程安全?怎么扩展线程安全的类?

    摘要:什么时候会出现线程不安全操作并非原子。只有单个组件,且它是线程安全的。这种情况下,就是的线程安全实际是委托给了整个表现出了线程安全。 当多个线程去访问某个类时,如果类会表现出我们预期出现的行为,那么可以称这个类是线程安全的。 什么时候会出现线程不安全? 操作并非原子。多个线程执行某段代码,如果这段代码产生的结果受不同线程之间的执行时序影响,而产生非预期的结果,即发生了竞态条件,就会...

    wh469012917 评论0 收藏0
  • 线程基础必要知识点!看了学习多线程事半功倍

    摘要:是需要我们去处理很多事情,为了防止多线程给我们带来的安全和性能的问题下面就来简单总结一下我们需要哪些知识点来解决多线程遇到的问题。 前言 不小心就鸽了几天没有更新了,这个星期回家咯。在学校的日子要努力一点才行! 只有光头才能变强 回顾前面: 多线程三分钟就可以入个门了! Thread源码剖析 本文章的知识主要参考《Java并发编程实战》这本书的前4章,这本书的前4章都是讲解并发的基...

    YPHP 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<