Java thread local storage ThreadLocal

Foreword

  • ThreadLocal is a  non-synchronous  thread-safe implementation
  • It reflects the  Thread-Specific Storage pattern: even if only one entrance, the interior will be allocated for each thread-specific storage space, the threads  do not share resources
  • This paper will summarize  ThreadLocal the usage and implementation details, I hope I could help

ThreadLocal mind map

Thread Security Diagrams

1. Usage

ThreadLocal Was easy to use,  ThreadLocal it offers the following public and protected method, this article will refer to  android.os.Looper.java  as an example to explain the  ThreadLocal usage:

ThradlLocal UML class diagram

// /frameworks/base/core/java/android/os/Looper.java

public class Looper {

    // ...

    // sThreadLocal.get() will return null unless you've called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } // 设置线程局部变量的值 sThreadLocal.set(new Looper(quitAllowed)); } public static Looper myLooper() { // 获取线程局部变量的值 return sThreadLocal.get(); } public static void prepare() { prepare(true); } // ... }
  • ThreadLocal Is a  static final variable  , is a generic parameter  Looper , acceptance of  Looper the value of the type
  • Looper#prepare() Calling  ThreadLocal#set() set  the value of the variable's value without disturbing each other, a different set of threads, not overwrite each other
  • Looper#myLooper() Calling  ThreadLocal#get() acquisition  value of a variable, the value of non-interfering get different threads

Timethreads图 - 01

  • Subclass  rewrite ThreadLocal#initialValue()  , you can set the variable initial values, we view the source code:

    public ConcurrentHashMap() {
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
    }
    public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) { if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) throw new IllegalArgumentException(); if (concurrencyLevel > MAX_SEGMENTS) concurrencyLevel = MAX_SEGMENTS; // Find power-of-two sizes best matching arguments int sshift = 0; int ssize = 1; while (ssize < concurrencyLevel) { ++sshift; ssize <<= 1; } = this.segmentShift 32 - sshift; // a high level, which is determined to fall Segment this.segmentMask = ssize The - . 1; // for modulo. Before indexFor method hashmap are mentioned. N-th power of -12 IF (initialCapacity> MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; int = initialCapacity C / ssize The; IF (ssize The C * <initialCapacity) ++ C; int = MIN_SEGMENT_TABLE_CAPACITY CAP; the while (CAP <C) << CAP = . 1; // Create Segments and Segments [0] Segment <K, V> S0 = new new Segment <K, V> (loadFactor, ( int) (* loadFactor CAP), (HashEntry <K, V> []) new new HashEntry [CAP]); // initialize the first position Segment Segment <K, V> [] = SS (Segment <K, V> []) new new Segment [ssize the]; // initialize Segments UNSAFE.putOrderedObject (ss , SBASE,// ordered write of segments[0] this.segments = ss; }
    • In  ThreadLocal#get() trying to get the value of variables, it will be called if an empty  ThreadLocal#setInitialValue() setting the initial value
    • Lazy Initialization  : until the first call  get() will be to set the initial value
    • Default  : initial value is set  null
  • ThreadLocal#remove() For  removing the  value previously stored variables. If the current thread next call  ThreadLocal#get() time, no  set() new values will still use  ThreadLocal#setInitialValue() set the initial value.

Here we can sum up  ThreadLocal the life cycle, as shown below:

ThreadLocal diagram of the life cycle

2. Programming Statute

remember? "Ali Baba Java Development Manual" mentioned about the  ThreadLocal programming of the Statute, as follows:

  • 5. [mandatory]  SimpleDateFormate is not thread-safe class, usually not defined as a  static  variable, if defined as static, it must be locked, or the use of  DateUtils tools

    Positive examples:

    private static final ThreadLocal<DataFormat> df = new ThreadLocal<DateFormat>(){
          @Override
          protected DateFormat initialValue(){ return new SimpleDateFormat("yyyy-MM-dd"); } };

    Description: If an application is JDK8, may be used  Instant instead of  Date ,  LocalDateTime instead of  CalendarDateTimeFormatter instead of  SimpleDateFormat , official explanation given: simple beautiful strong immutable thread-safe .

  • 15. [Reference] (the original is too long-winded, the following is the author paraphrased)  ThreadLocal variable recommends using  static  modification, can guarantee to create variable initialization in the class, all class instances share the same static variable.

    Noticed? In the beginning of the article Looper.java source, the  ThreadLocal variable is the use of  static modified

See here, I believe you have mastered the  ThreadLocal usage, the next article will delve  ThreadLocal inside to explore the implementation details of the data structure.

Segment

ConcurrentHashMap is composed of a plurality of Segment, Segment inherited ReentrantLock, every lock is on a Segment, it will not affect other Segment, to achieve the separation lock (also known as sub-lock) role.

Each Segment also contains the HashEntry array, HashEntry is a linked list. As shown below:

concurrencyLevel: concurrent, default 16, a direct impact on the value of segmentShift and segmentMask, and the number of initialization Segment. Segment number of initialization, and larger than the run closest to the value equal to N-th power of 2, such concurrencyLevel = 16, the number of Segment 16, concurrencyLevel = 17, the number of Segment 32. SegmentShift value is such that, for example Segment 32, 5 with respect to the power of 2, then his value is 32-5, for the time 27, 27 behind the unsigned right shift, which is to take the upper 5 bits, is value of 0 to 31, subscript Segment case is 0 to 31, the modulus corresponding to each Segment. 2 is the power of n segmentMask -1, here n is 5, a modulo. Before indexFor method hashmap are mentioned.

Guess you like

Origin www.cnblogs.com/aishangJava/p/11267562.html