zoukankan      html  css  js  c++  java
  • ThreadLocal小试牛刀

    ThreadLocal中保存的数据只能被当前线程私有,不被其它线程可见

    证明

    声明一个全局的变量threadLocal,初始值为1,通过3个线程对其进行访问修改设置,理论上threadLocal的最终值应该是6,然而我们的输出结果是3,说明了threadLocal中存放的数据是各自线程私有的

    package com.mmall.concurrency.example.threadLocal;
    
    public class UseThreadLocal {
        static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
            @Override
            protected Integer initialValue() {
                return 1;
            }
        };
    
    
        //运行3个线程
        public void startThreadArray() {
            Thread[] thread = new Thread[3];
            for (int i = 0; i < thread.length; i++) {
                thread[i] = new Thread(new MyThread(i));
            }
    
            for (int i = 0; i < thread.length; i++) {
                thread[i].start();
            }
        }
    
        private class MyThread implements Runnable {
            int id;
    
            public MyThread(int i) {
                id = i;
            }
    
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+":start");
                Integer v = threadLocal.get();
                v=v+id;
                threadLocal.set(v);
                System.out.println(Thread.currentThread().getName()+":"+threadLocal.get());
            }
        }
    
        public static void main(String[] args) {
            UseThreadLocal useThreadLocal = new UseThreadLocal();
            useThreadLocal.startThreadArray();
        }
    }
    
    

    结果

    Thread-0:start
    Thread-2:start
    Thread-1:start
    Thread-0:1
    Thread-2:3
    Thread-1:2
    

    小应用

    ThreadLocal结合过滤器和拦截器进行搭配使用,通过在过滤器HttpFilter设置ThreadLocal中的值,通过拦截器HttpInterceptor移除拦截器中的值

    编写`ThreadLocal类,包含设置、获取、移除操作

    package com.mmall.concurrency.example.threadLocal;
    
    public class RequestHolder {
    
        private final static ThreadLocal<Long> 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();
        }
    }
    
    

    编写过滤器HttpFilter类,通过在doFilter方法中对ThreadLocal进行存数据

    package com.mmall.concurrency;
    
    import com.mmall.concurrency.example.threadLocal.RequestHolder;
    import lombok.extern.slf4j.Slf4j;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
    @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() {
    
        }
    }
    
    

    编写ThreadLocalController类,在业务中可以获取到在过滤器HttpFilter中对ThreadLocal中存放的数据

    package com.mmall.concurrency.example.threadLocal;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    @RequestMapping("/threadLocal")
    public class ThreadLocalController {
    
        @RequestMapping("/test")
        @ResponseBody
        public Long test() {
            return RequestHolder.getId();
        }
    }
    
    

    编写拦截器HttpInterceptor类,在完成业务逻辑处理后,在拦截器类HttpInterceptorafterCompletion方法中移除我们在过滤器HttpFilter中对ThreadLocal设置的值

    package com.mmall.concurrency;
    
    import com.mmall.concurrency.example.threadLocal.RequestHolder;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @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;
        }
    }
    
    

    编写springboot的启动类ConcurrencyApplication,实例化了FilterRegistrationBean

    package com.mmall.concurrency;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @SpringBootApplication
    public class ConcurrencyApplication extends WebMvcConfigurerAdapter{
    
    	public static void main(String[] args) {
    		SpringApplication.run(ConcurrencyApplication.class, args);
    	}
    
    	@Bean
    	public FilterRegistrationBean httpFilter() {
    		FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    		registrationBean.setFilter(new HttpFilter());
    		registrationBean.addUrlPatterns("/threadLocal/*");
    		return registrationBean;
    	}
    
    	@Override
    	public void addInterceptors(InterceptorRegistry registry) {
    		registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/**");
    	}
    }
    
    

    启动springboot启动类,访问http://localhost:8080/threadLocal/test,控制台输出

    1571820790890

    本文由博客一文多发平台 OpenWrite 发布!

  • 相关阅读:
    JavaSE 基础 第51节 定义自己的异常
    JavaSE 基础 第50节 Java中的异常链
    JavaSE 基础 第49节 手动抛出异常
    JavaSE 基础 第48节 Java中的异常声明
    JavaSE 基础 第47节 获取异常信息
    JavaSE 基础 第46节 异常的分类
    JavaSE 基础 第45节Java异常快速入门
    JavaSE 基础 第44节 引用外部类的对象
    JavaSE 基础 第43节 静态内部类
    通用爬虫
  • 原文地址:https://www.cnblogs.com/lisingshen/p/11782271.html
Copyright © 2011-2022 走看看