ThreadLocalのスレッドプール

問題

Webプロジェクトは、毎回ユーザのログインシステムはRedisのセッション情報が保存され、その後、示されているように、クライアントトークン、トークンユーザーセッションに返されますが、後続のすべての要求は、セッショントークン情報に基づいて、このインターセプタをインターセプタがかかりますThreadLocalのに戻ってからのRedisを取ります。場合はより多くの同時、エラーに関するセッション情報が起こります。

解析エラープロセスである:1ユーザログとセッション情報とユーザTheadLocalのデポジットを通すために1スレッドを使用して、この時点でシステムにアクセスし、ユーザがシステムにアクセスし、また2ログインしていない、サーバは再びスレッドを割り当てます要求、ユーザーの1つのセッション情報に2を取るために、ユーザーを処理するために。

ThreadLocalの

TheadLocalは、スレッド変数のJDKは非常に使いやすいツールを提供して共有されています。ウェブを開発する場合、サーバは、応答を要求TheadLocal要求を格納するために使用することができます。方法で通過することなく、コールスタックに示します。任意の場所を簡単にインスタンス変数に私たちの預金を取得するために、スレッドメソッドでスタックを呼び出すことができます。

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()
        // ...
    }
}
复制代码

TheadLocalコードを見て:

// 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セットまたは最初ますメソッドメソッドを取得しThread t = Thread.currentThread();、現在のスレッドのインスタンスを取得します。そして、TheadLocalMapインスタンスのスレッドのインスタンスを取得ThreadLocalMap map = getMap(t);各スレッドのインスタンス変数は、独自のスレッドに格納されているため、これらの変数はスレッドセーフになるようにスレッド変数を取得している理由は、同じスレッド内の同じインスタンスを獲得します。

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

これらは、Threadクラスの宣言されているthreadLocalsプロパティ。スレッド変数実際のストレージことがわかるThreadLocal.ThreadLocalMapクラス、ストレージ・キーとキー例をねじ切りされたマップ(キー値)、上のように、値が変数スレッドです。

Tomcatのスレッドプール

オペレーティングシステムがリソースを消費しているスレッドを作成するため、非常に多くのアプリケーションがスレッドプールモードを使用すると、システムの初期化は一回の一定量を作成することで、これらのスレッドが共有する多重化、スレッド後に使用されていないことアプリケーションが停止されるまで、それは破壊されます。

この結果は、別のユーザーの要求が同じスレッドが混乱セッション情報を引き起こし、異なるユーザによって得られた同じセッション情報につながる再利用するということです。

解きます

一の構成ではインターセプター、要求された前端ローカルセッションスレッド変数の設定情報は、后端セッション情報は、スレッドローカル変数を空にする。

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

概要

ThreadLocalのは、私たちは、データのスレッド・セーフな方法の保証を提供するためのスレッドで変数を共有するための便利な方法を提供します。しかし、もし再利用し、マルチスレッド環境でのスレッドの場合を考えるThreadLocal情報は、タスクのクリーンアップするスレッドの終了時など、ユーザーのセッションに関連する情報である保存内ThreadLocalの情報を。

おすすめ

転載: juejin.im/post/5d4e16be6fb9a06aca380c9b