ThreadLocalとは

3587 ワード

今、アンテナプールが実現して、ThreadLocalを使っているところを見て、ThreadLocalというものを研究してみると、面白いことに気づきました.
ソース研究から見たThreadLocalの実現原理
 
package com.sogou.game.cms.pool;

import org.apache.thrift.transport.TSocket;

public class ConnectionManager {
	ThreadLocal<TSocket> socketThreadSafe = new ThreadLocal<TSocket>();

	/**       */
	public ConnectionProvider connectionProvider;

	public ConnectionManager(){
		connectionProvider=new ConnectionProviderImpl();
	}
	/**
	*  socket
	* @return TSocket
	*/
	public TSocket getSocket() {
		TSocket socket = null;
		try {
			socket = connectionProvider.getConnection();
			socketThreadSafe.set(socket);

			return socketThreadSafe.get();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			connectionProvider.returnCon(socket);
			socketThreadSafe.remove();
		}

		return socket;
	}

	public ConnectionProvider getConnectionProvider() {
		return connectionProvider;
	}

	public void setConnectionProvider(ConnectionProvider connectionProvider) {
		this.connectionProvider = connectionProvider;
	}

}
 
 
このコードにはThreadLocalが使用されていますが、ThreadLocalは使用時にstatic変数として宣言されるのが一般的で、後でソースコードを分析するときになぜstaticなのかと言います.
ThreadLocal
ThreadLocalのgetメソッドを見てみましょう
 
public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }

 
現在のスレッドを取得し、getMap()に現在のスレッドを転送してThreadLocalMapを取得します.
以下はThreadLocalMapの実現方式であり、簡単にmapと考えることができ、keyはThreadLocal値であり、valueはsetする値である.
 
 
static class ThreadLocalMap {

        /**
         * The entries in this hash map extend WeakReference, using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced, so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
        static class Entry extends WeakReference<ThreadLocal> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }
}

 
getMapメソッドの続行
 
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

Thread tのthreadLocalsの値を返しますが、threadLocalsは何ですか?
 
ThreadLocal.ThreadLocalMap threadLocals = null;

ぐるっと回ったのにどうしてまた帰ってきたのか.
考えを整理する
static ThreadLocalはsetの場合setからThreadまでの独自のThreadLocalMapでkeyはthreadlocal変数
ThreadLocalの役割が明らかになった
マルチスレッドでは、ThreadA、ThreaddBを仮定すると、staticのThreadLocalは同じであり、ThreadAがsetメソッドを実行する場合は、対応するkey、value set独自のThreadLocalMapであり、getメソッドの原理も同様である.keyは変わらないので、マルチスレッドがget、set時に自身がset、get時に値を取ることを保証します.これもなぜThreadLocalが一般的にstaticなのかということです.