最近公司在進行Java開發人員的招聘活動,其中有一道面試題是這樣的:“請簡單描述一下ThreadLocal類的作用。” 結果發現有很多的面試者沒有聽說過ThreadLocal或者聽說過卻不知道這個類究竟是用來做什麼的。 因此這裏寫一篇博客來介紹一下ThreadLocal這個類。
2. 共享狀態不可變。 假設某條數據被多線程共享,然而該數據是不可變數據,那麼它便沒有多線程問題。舉例來說: Java中的String類型就是不可變的,因此String的共享並不會導致多線程安全問題。
- /**
- * Returns the value in the current thread's copy of this
- * thread-local variable. If the variable has no value for the
- * current thread, it is first initialized to the value returned
- * by an invocation of the {@link #initialValue} method.
- *
- * @return the current thread's value of this thread-local
- */
- 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();
- }
- /**
- * Sets the current thread's copy of this thread-local variable
- * to the specified value. Most subclasses will have no need to
- * override this method, relying solely on the {@link #initialValue}
- * method to set the values of thread-locals.
- *
- * @param value the value to be stored in the current thread's copy of
- * this thread-local.
- */
- public void set(T value) {
- Thread t = Thread.currentThread();
- ThreadLocalMap map = getMap(t);
- if (map != null)
- map.set(this, value);
- else
- createMap(t, value);
- }
我們來看一個在Hibernate中使用ThreadLocal的例子:
- private static ThreadLocal<Connection> connectionHolder
- = new ThreadLoca<Connection>() {
- public Connection initialValue() {
- return DriverManager.getConnection(DB_URL);
- }
- };
- public static Connection getConnection() {
- return ConnectionHolder.get();
- }
上面的例子是一個最經典的ThreadLocal使用案例: 在單線程中創建一個單例變量,並在程序啓動時初始化該單例變量,從而避免在調用每個方法時都要傳遞該變量。然而該單例可能並不是線程安全的,因此,當多線程應用程序在沒有互相協作的情況下,可以通過將該單例變量保存到ThreadLocal中,以確保每一個線程都擁有屬於自己的實例。
在這裏,一個更好理解的說法便是:該單例是一個線程內單例,在多線程應用中,每個線程裏都有一個該單例。
通過學習ThreadLocal,我們能夠對正確的在項目中使用它,同時,也能夠幫助我們對多線程編程有一個更深的認識.
(該文同時發表在http://mabusyao.iteye.com/blog/2224898)