ThreadLocalとは
3587 ワード
今、アンテナプールが実現して、ThreadLocalを使っているところを見て、ThreadLocalというものを研究してみると、面白いことに気づきました.
ソース研究から見たThreadLocalの実現原理
このコードにはThreadLocalが使用されていますが、ThreadLocalは使用時にstatic変数として宣言されるのが一般的で、後でソースコードを分析するときになぜstaticなのかと言います.
ThreadLocal
ThreadLocalのgetメソッドを見てみましょう
現在のスレッドを取得し、getMap()に現在のスレッドを転送してThreadLocalMapを取得します.
以下はThreadLocalMapの実現方式であり、簡単にmapと考えることができ、keyはThreadLocal値であり、valueはsetする値である.
getMapメソッドの続行
Thread tのthreadLocalsの値を返しますが、threadLocalsは何ですか?
ぐるっと回ったのにどうしてまた帰ってきたのか.
考えを整理する
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なのかということです.
ソース研究から見た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なのかということです.