3/05/2014
5:46:00 PM 0

Java ThreadLocal

ThreadLocal 的用途 : ThreadLocal 是在多執行緒中儲存變數值的方式,當不同 thread 共用 ThreadLocal 實例,可設定和讀取屬於自身 Thread 的變數值而不相互干擾,用 thread local variable 來稱呼它或許更為恰當,其概念正好與 singleton 相反

ThreadLocal 提供 3 個 public method 與 1 個 protected method
T get()
protected  T initialValue()
void remove()
void set(T value)
ThreadLocal 內部儲存值的方式, 其實是利用到 thread 實例中的 threadLocals 實例變數(instance variable),threadLocals 是個類似於 HashMap 的物件, ThreadLocal 將自身實例當作 key, 將 set 的值設定到 threadLocals 物件參考中

ThreadLocal set method source code
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);//reference to t.threadLocals
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);//t.threadLocals = new ThreadLocalMap(this, value);
}
ThreadLocal set 的資料實際上是儲存於 thread instance 中, 這樣做的好處是當該 thread instance 被 GC 後 ThreadLocal 儲存的參考也跟著消失了,不會有記憶體洩漏(memory leak)的問題

ThreadLocal example:
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class TestThreadLocal {

    private final static ThreadLocal<Date> endDate = new ThreadLocal<Date>() {
        @Override
        protected Date initialValue() {
            return new Date();
        }
    };

    public static void main(String[] args) {
        final ExecutorService exec = Executors.newCachedThreadPool();
        final Runnable task = () -> { //Java lambda expression
            try {
                TimeUnit.SECONDS.sleep((int) Math.rint(Math.random() * 10));
            } catch (final InterruptedException e) {

                e.printStackTrace();
            }

            System.out.printf("Thread Completed: %1$d : %2$tF %2$tT%n", Thread
                    .currentThread().getId(), TestThreadLocal.endDate.get());
        };

        for (int i = 0; i < 10; i++) {
            exec.execute(task);
        }

        exec.shutdown();
    }
}

0 comments:

Post a Comment