ThreadLocal thread pool

problem

Web project, each time a user login system will redis Session information is stored, and then returned to the client token, the token user session as indicated, all subsequent requests will take an interceptor, this interceptor based on the Session token information take redis from the back into a ThreadLocal. When more concurrent, Session information about the error happens.

The analysis error process is: 1 user log in and access the system at this time using Session information and user thread A 1 to thread A deposit of TheadLocal, then a user is not logged 2 also access the system, server allocates the threads again a to handle the request, then the user to take 2 to 1 Session information of the user.

ThreadLocal

TheadLocal is shared thread variable jdk provides a very easy to use tool. When developing Web, the server may be used to store request TheadLocal Request, Response. In the method shown in the call stack without passing. Any place can easily call stack in the thread method to get our deposit into the instance variables.

class WebContext {
    private TheadLocal<HttpServletRequest> request = new TheadLocal<>();
    private TheadLocal<HttpServletResponse> response = new TheadLocal<>();
    public static void setRequest(HttpServletRequest req) {
        request.set(req);
    }
    public static HttpServletRequest getRequest() {
        request.get();
    }
    public static void setResponse(HttpServletResponse resp) {
        response.set(resp);
    }
    public static HttpServletResponse getResponse() {
        response.get();
    }
}

class AbcController {
    public Object userInfo() {
        HttpServletRequest request = WebContext.getRequest();
        // request.getParameter()
        // ...
    }
}
复制代码

Look TheadLocal code:

// TheadLocal两个重要的方法
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}
public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}
复制代码

TheadLocal either set or get method method will first Thread t = Thread.currentThread();obtain the current thread instance. Then get TheadLocalMap instance thread instance ThreadLocalMap map = getMap(t);which is why acquiring thread variable will win the same instance in the same thread, because each thread instance variables are stored in its own thread so that these variables are thread-safe.

public class Thread implements Runnable {
    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
}
复制代码

These are the Thread class declaration of threadLocalsproperty. It can be seen that the thread variable actual storage ThreadLocal.ThreadLocalMapclass, storage key and the like on Map (Key-Value), which is threaded Key example, Value is a variable thread.

Tomcat thread pool

Because the operating system to create a thread that is resource-consuming, so many applications will use thread pool mode, system initialization is to create a certain amount of one-time, multiplex these threads will share, that is not used up after thread It will be destroyed until the application is stopped.

Result of this is that different user requests reuse the same thread leads to the same Session information obtained by different users, causing confusion Session information.

solve

In one arrangement an interceptor, the requested 前端setting information to the local Session thread variable, the 后端Session information emptying thread-local variables.

// 代码简化了
public class SessionInspector extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(...) throws Exception {
        // ThreadLocal.set(Session)
        return true;
    }
    
    public void afterCompletion(...) {
        // ThreadLocal.clear()
    }
}
复制代码

to sum up

ThreadLocal provides a convenient way to share variable in the thread for us to provide a guarantee of data thread-safe manner. But consider the case of a thread in a multithreaded environment, reuse, if ThreadLocalwithin the save information is information related to the user's session, etc. At the end of the thread to clean up the task ThreadLocalinformation in the.

Guess you like

Origin juejin.im/post/5d4e16be6fb9a06aca380c9b