Java multi-threading - thread-safe in Spring

Why we generally use the Spring bean thread safe?

Created in the default scope in spring bean is singleton, the object is to create a single example , the next and when we use these bean, as we often use the Service, DAO and Controller, most cases are based on similar tools the form, but these bean method invocation, the bean does not have a property, status changes, so there is no multi-threaded competition, that is thread-safe.

If we want to change the properties of how to ensure these bean thread-safe?

By scope to prototype

When the scope is set to prototype, each time the object is will reconstruct the object, so the properties (member variables) are thread unique object is thread-safe. However, such a multi-object creation and destruction will take up a lot of memory and consumes system resources, but recommended the following threadlocal.

By using ThreadLocal

When the properties of the synchronization object does not need to be shared with other threads, you only need to ensure that closed itself thread used without being modified by other threads

Threadloca principle

Reference: the Java multithreading - ThreadLocal

Demo:

In each class the request by threadlocal shared variables, by filter, interceptor shared authentication success. Print filter value threadlocal, the set value threadlocal before interceptor and print, delete the value threadlocal after the interceptor, to avoid memory leaks. (: Separately for convenience of explanation when needed, it will be sent to all the code a class file, implemented using ps)

import lombok.extern.slf4j.Slf4j;
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.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * \* Created with IntelliJ IDEA.
 * \* @author: zuzi
 * \* Date: 2019-06-11
 * \* Time: 下午12:06
 * \* Description:
 * \
 */
@Slf4j
@SpringBootApplication
public class JavaStudyApplication implements WebMvcConfigurer {
    public static void main(String[] args) {
        SpringApplication.run(JavaStudyApplication.class, args);
    }

    public static final ThreadLocal threadLocal = new ThreadLocal<>();


    @RestController("thread-local")
    class ThreadLocalController {
        @PostMapping
        public String threadLocalSet() {
            threadLocal.set("controller set");
            return "设置成功!";
        }

        @GetMapping
        public String threadLocalGet() {
            return "获取到的threadLocal:为" + threadLocal.get();
        }
    }

    class HttpFilter implements Filter {
        @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(), threadLocal.get());
            filterChain.doFilter(request, servletResponse);
        }
    }

    class HttpInterceptor extends HandlerInterceptorAdapter {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            threadLocal.set("interceptor set");
            log.info("pre handle , threadLocal:" + threadLocal.get());
            return true;
        }

        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("after completion, threadLocal:" + threadLocal.get());
            threadLocal.remove();
        }
    }


    @Bean
    public FilterRegistrationBean httpFilter() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new HttpFilter());
        registrationBean.addUrlPatterns("/thread-local/*");
        return registrationBean;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/**");
    }
}
复制代码

Results show

When requested GET /thread-local, since the print result threadlocal filter is not set to null, set before the interceptor ThreadLocal, so printing interceptor SET, is also provided in the controller, the return value SET interceptor, the interceptor is empathy interceptor set.

request:

Log:

When requested POST /thread-local, the similar results were as follows:

request:

Log:

By locking

When using the shared property of the synchronization object in multiple threads, refer to: the Java multithreading - lock mechanism

Guess you like

Origin juejin.im/post/5d0dc6a2e51d4510b71da612