ThreadLocal源码阅读

  1 package java.lang;
  2 
  3 import java.lang.ref.WeakReference;
  4 import java.util.Objects;
  5 import java.util.concurrent.atomic.AtomicInteger;
  6 import java.util.function.Supplier;
  7 
  8 /**
  9  * This class provides thread-local variables.  These variables differ from
 10  * their normal counterparts in that each thread that accesses one (via its
 11  * {@code get} or {@code set} method) has its own, independently initialized
 12  * copy of the variable.  {@code ThreadLocal} instances are typically private
 13  * static fields in classes that wish to associate state with a thread (e.g.,
 14  * a user ID or Transaction ID).
 15  * 本类提供线程局部变量。这些变量和普通变量不同,每一个线程访问(通过get和set方法)
 16  * 的变量都是属于线程的独立初始化的一个线程局部变量的副本。线程局部变量通常是类中希望
 17  * 将状态与线程关联的私有静态域(如用户ID和事务ID)。
 18  *
 19  * 

For example, the class below generates unique identifiers local to each 20 * thread. 21 * 例如,下面的类生成每个线程本地的唯一标识符。 22 * A thread's id is assigned the first time it invokes {@code ThreadId.get()} 23 * and remains unchanged on subsequent calls. 24 * 一个线程的Id在该线程首次调用get方法时生成,且在后续通话中保持不变。 25 *

 26  * import java.util.concurrent.atomic.AtomicInteger;
 27  *
 28  * public class ThreadId {
 29  *     // Atomic integer containing the next thread ID to be assigned
 30  *     private static final AtomicInteger nextId = new AtomicInteger(0);
 31  *
 32  *     // Thread local variable containing each thread's ID
 33  *     private static final ThreadLocal threadId =
 34  *         new ThreadLocal() {
 35  *             @Override
 36  *             protected Integer initialValue() {
 37  *                 return nextId.getAndIncrement();
 38  *         }
 39  *     };
 40  *
 41  *     // Returns the current thread's unique ID, assigning it if necessary
 42  *     public static int get() {
 43  *         return threadId.get();
 44  *     }
 45  * }
 46  * 
47 *

Each thread holds an implicit reference to its copy of a thread-local 48 * variable as long as the thread is alive and the {@code ThreadLocal} 49 * instance is accessible; after a thread goes away, all of its copies of 50 * thread-local instances are subject to garbage collection (unless other 51 * references to these copies exist). 52 * 只要线程还活着,且ThreadLocal实例能够被访问,每个线程均保留其线程局部变量 53 * 副本的隐式引用;线程死后它的所有线程局部变量副本被垃圾回收器回收(除非存在 54 * 对这些线程局部变量副本的其他应用) 55 * 56 * @author Josh Bloch and Doug Lea 57 * @since 1.2 58 */ 59 public class ThreadLocal { 60 /** 61 * ThreadLocals rely on per-thread linear-probe hash maps attached 62 * to each thread (Thread.threadLocals and inheritableThreadLocals). 63 * ThreadLocal的实例依赖于每个线程的线性探针哈希图附加到每个线程。 64 * The ThreadLocal objects act as keys,searched via threadLocalHashCode. 65 * ThreadLocal对象充当键,通过threadLocalHashCode搜索。 66 * This is a custom hash code 67 * (useful only within ThreadLocalMaps) that eliminates collisions 68 * in the common case where consecutively constructed ThreadLocals 69 * are used by the same threads, while remaining well-behaved in 70 * less common cases. 71 * 这是一个自定义哈希码(仅在ThreadLocalMaps中有用),在相同的线程使用连续构造 72 * 的ThreadLocals的常见情况下,它消除了冲突,而在不太常见的情况下,它们表现良好。 73 */ 74 private final int threadLocalHashCode = nextHashCode(); 75 76 /** 77 * The next hash code to be given out. Updated atomically. Starts at 78 * zero. 79 * 下一次给出的哈希码,该值的自动更新不能被中断(原子性),值从0开始累加。 80 */ 81 private static AtomicInteger nextHashCode = 82 new AtomicInteger(); 83 84 /** 85 * The difference between successively generated hash codes - turns 86 * implicit sequential thread-local IDs into near-optimally spread 87 * multiplicative hash values for power-of-two-sized tables. 88 * 连续生成的哈希码间的差值, 89 */ 90 private static final int HASH_INCREMENT = 0x61c88647; 91 92 /** 93 * Returns the next hash code. 94 * 返回下一个哈希码 95 */ 96 private static int nextHashCode() { 97 return nextHashCode.getAndAdd(HASH_INCREMENT); 98 } 99 100 /** 101 * Returns the current thread's "initial value" for this 102 * thread-local variable. This method will be invoked the first 103 * time a thread accesses the variable with the {@link #get} 104 * method, unless the thread previously invoked the {@link #set} 105 * method, in which case the {@code initialValue} method will not 106 * be invoked for the thread. Normally, this method is invoked at 107 * most once per thread, but it may be invoked again in case of 108 * subsequent invocations of {@link #remove} followed by {@link #get}. 109 * 翻译: 110 * 返回当前线程持有的线程局部变量副本的初始值。线程在第一次通过get方法访问局部 111 * 变量前如果没有调用过set方法为局部变量设置值,本函数就会被调用。通常每个线程 112 * 最多会调用一次本方法,但是如果在之后依次调用了remove和get方法,它可能会再次被调用。 113 * 114 *

This implementation simply returns {@code null}; if the 115 * programmer desires thread-local variables to have an initial 116 * value other than {@code null}, {@code ThreadLocal} must be 117 * subclassed, and this method overridden. Typically, an 118 * anonymous inner class will be used. 119 * 本实现仅返回null,如果开发者希望线程的局部变量具体其他初始值,只能通过声明子类并 120 * 重写本方法。通常,将使用匿名内部类。(下面就有一个内部类) 121 * 122 * @return the initial value for this thread-local 123 */ 124 protected T initialValue() { 125 return null; 126 } 127 128 /** 129 * Creates a thread local variable. The initial value of the variable is 130 * determined by invoking the {@code get} method on the {@code Supplier}. 131 * 创建一个线程局部变量的副本,变量的初始值是通过调用Supplier上的get方法确定的。 132 * (Supplier是一个函数式接口) 133 * 134 * @param the type of the thread local's value 135 * @param supplier the supplier to be used to determine the initial value 136 * @return a new thread local variable 137 * @throws NullPointerException if the specified supplier is null 138 * @since 1.8 139 */ 140 public static ThreadLocal withInitial(Supplierextends S> supplier) { 141 return new SuppliedThreadLocal<>(supplier); 142 } 143 144 /** 145 * 构造函数 146 * Creates a thread local variable. 147 * 148 * @see #withInitial(java.util.function.Supplier) 149 */ 150 public ThreadLocal() { 151 } 152 153 /** 154 * Returns the value in the current thread's copy of this 155 * thread-local variable. If the variable has no value for the 156 * current thread, it is first initialized to the value returned 157 * by an invocation of the {@link #initialValue} method. 158 * 译: 159 * 返回当前线程持有的线程局部变量副本的值。如果该变量还没赋值, 160 * 则先使用initialValue方法为其赋予初始值。 161 * 162 * @return the current thread's value of this thread-local 163 */ 164 public T get() { 165 //1、确定当前线程 166 Thread t = Thread.currentThread(); 167 //2、 168 ThreadLocalMap map = getMap(t); 169 if (map != null) { 170 ThreadLocalMap.Entry e = map.getEntry(this); 171 if (e != null) { 172 @SuppressWarnings("unchecked") 173 T result = (T) e.value; 174 return result; 175 } 176 } 177 return setInitialValue(); 178 } 179 180 /** 181 * Variant of set() to establish initialValue. Used instead 182 * of set() in case user has overridden the set() method. 183 * 译: 184 * set方法的变体,用于设置初始值。如果用户已覆盖set()方法, 185 * 请使用它代替set()。 186 * 187 * @return the initial value 188 */ 189 private T setInitialValue() { 190 T value = initialValue(); 191 Thread t = Thread.currentThread(); 192 ThreadLocalMap map = getMap(t); 193 if (map != null) 194 map.set(this, value); 195 else 196 createMap(t, value); 197 return value; 198 } 199 200 /** 201 * Sets the current thread's copy of this thread-local variable 202 * to the specified value. Most subclasses will have no need to 203 * override this method, relying solely on the {@link #initialValue} 204 * method to set the values of thread-locals. 205 * 译: 206 * 设置当前线程持有的线程局部变量副本的值为指定值。大部分子类不需要重写本 207 * 方法,仅依靠initialValue方法来设置值。 208 * 209 * @param value the value to be stored in the current thread's copy of 210 * this thread-local. 211 */ 212 public void set(T value) { 213 Thread t = Thread.currentThread(); 214 ThreadLocalMap map = getMap(t); 215 if (map != null) 216 map.set(this, value); 217 else 218 createMap(t, value); 219 } 220 221 /** 222 * Removes the current thread's value for this thread-local 223 * variable. If this thread-local variable is subsequently 224 * {@linkplain #get read} by the current thread, its value will be 225 * reinitialized by invoking its {@link #initialValue} method, 226 * unless its value is {@linkplain #set set} by the current thread 227 * in the interim. This may result in multiple invocations of the 228 * {@code initialValue} method in the current thread. 229 * 译: 230 * 移除单前线程持有的线程本地变量的值。如果随后马上又通过get方法试图获取 231 * 这个线程本地变量的值,这个变量的值会再次通过调用initialValue方法确定, 232 * 除非在调用get方法前通过set方法设置了值就不会。这可能会导致initialValue 233 * 方法被当前线程多次调用。 234 * 235 * @since 1.5 236 */ 237 public void remove() { 238 ThreadLocalMap m = getMap(Thread.currentThread()); 239 if (m != null) 240 m.remove(this); 241 } 242 243 /** 244 * Get the map associated with a ThreadLocal. Overridden in 245 * InheritableThreadLocal. 246 * 247 * @param t the current thread 248 * @return the map 249 */ 250 ThreadLocalMap getMap(Thread t) { 251 return t.threadLocals; 252 } 253 254 /** 255 * Create the map associated with a ThreadLocal. Overridden in 256 * InheritableThreadLocal. 257 * 258 * @param t the current thread 259 * @param firstValue value for the initial entry of the map 260 */ 261 void createMap(Thread t, T firstValue) { 262 t.threadLocals = new ThreadLocalMap(this, firstValue); 263 } 264 265 /** 266 * Factory method to create map of inherited thread locals. 267 * Designed to be called only from Thread constructor. 268 * 269 * @param parentMap the map associated with parent thread 270 * @return a map containing the parent's inheritable bindings 271 */ 272 static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) { 273 return new ThreadLocalMap(parentMap); 274 } 275 276 /** 277 * Method childValue is visibly defined in subclass 278 * InheritableThreadLocal, but is internally defined here for the 279 * sake of providing createInheritedMap factory method without 280 * needing to subclass the map class in InheritableThreadLocal. 281 * This technique is preferable to the alternative of embedding 282 * instanceof tests in methods. 283 */ 284 T childValue(T parentValue) { 285 throw new UnsupportedOperationException(); 286 } 287 288 /** 289 * An extension of ThreadLocal that obtains its initial value from 290 * the specified {@code Supplier}. 291 * SuppliedThreadLocal类拓展了ThreadLocal类,该类重写了initialValue函数, 292 * 用于从指定的Supplier获取初始值。 293 */ 294 static final class SuppliedThreadLocal extends ThreadLocal { 295 296 /** 297 * Supplier是一个函数式接口 298 */ 299 private final Supplierextends T> supplier; 300 301 /** 302 * 构造函数 303 * 304 * @param supplier - 一个函数式接口,用来返回线程本地变量的初始值 305 */ 306 SuppliedThreadLocal(Supplierextends T> supplier) { 307 /** 308 * public static T requireNonNull(T obj) { 309 * if (obj == null) 310 * throw new NullPointerException(); 311 * return obj; 312 * } 313 */ 314 this.supplier = Objects.requireNonNull(supplier); 315 } 316 317 /** 318 * 这里很关键,需要去看看Supplier接口的源码。 319 */ 320 @Override 321 protected T initialValue() { 322 return supplier.get(); 323 } 324 } 325 326 /** 327 * ThreadLocalMap is a customized hash map suitable only for 328 * maintaining thread local values. No operations are exported 329 * outside of the ThreadLocal class. The class is package private to 330 * allow declaration of fields in class Thread. To help deal with 331 * very large and long-lived usages, the hash table entries use 332 * WeakReferences for keys. However, since reference queues are not 333 * used, stale entries are guaranteed to be removed only when 334 * the table starts running out of space. 335 * 译: 336 * ThreadLocalMap是自定义的HashMap,仅适用于维护线程局部变量的值。 337 * 没有操作导出到ThreadLocal类之外。这个类是包私有的,用于Thread类 338 * 域声明。为了处理存储空间消耗大,使用时间长的使用情况,这个HashTable 339 * 使用WeakReferences(弱引用)作为键。但是,由于未使用参考队列,因此 340 * 仅在表开始空间不足时,才保证删除过时的条目。 341 */ 342 static class ThreadLocalMap { 343 344 /** 345 * The entries in this hash map extend WeakReference, using 346 * its main ref field as the key (which is always a 347 * ThreadLocal object). Note that null keys (i.e. entry.get() 348 * == null) mean that the key is no longer referenced, so the 349 * entry can be expunged from table. Such entries are referred to 350 * as "stale entries" in the code that follows. 351 * 译: 352 * 该哈希表中的条目是WeakReference子类的对象,以其主域作为键(大多数情 353 * 况下是一个ThreadLocal对象)。需要注意,当以null作为键时,意味着这个 354 * 键已经不再被引用,因此这个键所在的条目能被表移除。这样的条目我们在下文 355 * 中称为“过时的条目” 356 */ 357 static class Entry extends WeakReference> { 358 /** 359 * The value associated with this ThreadLocal. 360 * 与ThreadLocal相关联的值 361 */ 362 Object value; 363 364 /** 365 * @param k - 以线程作为键 366 * @param v - 线程持有的threal-local变量副本的值 367 */ 368 Entry(ThreadLocal k, Object v) { 369 super(k); 370 value = v; 371 } 372 } 373 374 /** 375 * The initial capacity -- MUST be a power of two. 376 * 初始容量——必须是2的幂 377 */ 378 private static final int INITIAL_CAPACITY = 16; 379 380 /** 381 * The table, resized as necessary. 382 * table.length MUST always be a power of two. 383 * 译: 384 * 表在必要的时候会扩容,表的大小必须是2的幂 385 */ 386 private Entry[] table; 387 388 /** 389 * The number of entries in the table. 390 * 表中条目(键值对)的数量 391 */ 392 private int size = 0; 393 394 /** 395 * the next size value at which to resize. 396 * 下一次调整表的大小时要增加的值 397 */ 398 private int threshold; // Default to 0 399 400 /** 401 * Set the resize threshold to maintain at worst a 2/3 load factor. 402 * 从这里可以看出,每次扩容,容量增加2/3。 403 */ 404 private void setThreshold(int len) { 405 threshold = len * 2 / 3; 406 } 407 408 /** 409 * Increment i modulo len. 410 */ 411 private static int nextIndex(int i, int len) { 412 return ((i + 1 < len) ? i + 1 : 0); 413 } 414 415 /** 416 * Decrement i modulo len. 417 */ 418 private static int prevIndex(int i, int len) { 419 return ((i - 1 >= 0) ? i - 1 : len - 1); 420 } 421 422 /** 423 * Construct a new map initially containing (firstKey, firstValue). 424 * ThreadLocalMaps are constructed lazily, so we only create 425 * one when we have at least one entry to put in it. 426 * 译: 427 * 构造一个最初包含以下内容的新Map。ThreadLocalMaps是延迟创建的,所以 428 * 只有当至少要添加一条条目时才创建一个。 429 */ 430 ThreadLocalMap(ThreadLocal firstKey, Object firstValue) { 431 table = new Entry[INITIAL_CAPACITY]; 432 int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); 433 table[i] = new Entry(firstKey, firstValue); 434 size = 1; 435 setThreshold(INITIAL_CAPACITY); 436 } 437 438 /** 439 * Construct a new map including all Inheritable ThreadLocals 440 * from given parent map. Called only by createInheritedMap. 441 * 442 * @param parentMap the map associated with parent thread. 443 */ 444 private ThreadLocalMap(ThreadLocalMap parentMap) { 445 Entry[] parentTable = parentMap.table; 446 int len = parentTable.length; 447 setThreshold(len); 448 table = new Entry[len]; 449 450 for (int j = 0; j < len; j++) { 451 Entry e = parentTable[j]; 452 if (e != null) { 453 @SuppressWarnings("unchecked") 454 ThreadLocal key = (ThreadLocal) e.get(); 455 if (key != null) { 456 Object value = key.childValue(e.value); 457 Entry c = new Entry(key, value); 458 int h = key.threadLocalHashCode & (len - 1); 459 while (table[h] != null) 460 h = nextIndex(h, len); 461 table[h] = c; 462 size++; 463 } 464 } 465 } 466 } 467 468 /** 469 * Get the entry associated with key. This method 470 * itself handles only the fast path: a direct hit of existing 471 * key. It otherwise relays to getEntryAfterMiss. This is 472 * designed to maximize performance for direct hits, in part 473 * by making this method readily inlinable. 474 * 译: 475 * 获取键关联的条目。 476 * 理解: 477 * 散列表中通过哈希函数和键计算哈希码,使用哈希码来决定数据存储的位置, 478 * 不同的键通过哈希函数可能计算出相同的哈希码,这被称为“冲突”。遇到冲突 479 * 时需要使用某种“冲突解决策略”重新确定一个哈希码,本函数假设没有冲突, 480 * 尝试通过计算出来的哈希码直接取值。事实上好的哈希算法计算出来的哈希码 481 * 分布的比较均匀,即很少发生冲突。 482 * 483 * @param key the thread local object 484 * @return the entry associated with key, or null if no such 485 */ 486 private Entry getEntry(ThreadLocal key) { 487 //1、尝试直接取值 488 int i = key.threadLocalHashCode & (table.length - 1); 489 Entry e = table[i]; 490 if (e != null && e.get() == key) 491 return e; 492 else 493 return getEntryAfterMiss(key, i, e);//2、冲突解决方案 494 } 495 496 /** 497 * Version of getEntry method for use when key is not found in 498 * its direct hash slot. 499 * 500 * @param key the thread local object 501 * @param i the table index for key's hash code 502 * @param e the entry at table[i] 503 * @return the entry associated with key, or null if no such 504 */ 505 private Entry getEntryAfterMiss(ThreadLocal key, int i, Entry e) { 506 Entry[] tab = table; 507 int len = tab.length; 508 509 while (e != null) { 510 ThreadLocal k = e.get(); 511 if (k == key) 512 return e; 513 if (k == null) 514 expungeStaleEntry(i); 515 else 516 i = nextIndex(i, len); 517 e = tab[i]; 518 } 519 return null; 520 } 521 522 /** 523 * Set the value associated with key. 524 * 设置与键关联的值 525 * 526 * @param key the thread local object 527 * @param value the value to be set 528 */ 529 private void set(ThreadLocal key, Object value) { 530 531 // We don't use a fast path as with get() because it is at 532 // least as common to use set() to create new entries as 533 // it is to replace existing ones, in which case, a fast 534 // path would fail more often than not. 535 536 Entry[] tab = table; 537 int len = tab.length; 538 int i = key.threadLocalHashCode & (len - 1); 539 540 for (Entry e = tab[i]; 541 e != null; 542 e = tab[i = nextIndex(i, len)]) { 543 ThreadLocal k = e.get(); 544 545 if (k == key) { 546 e.value = value; 547 return; 548 } 549 550 if (k == null) { 551 replaceStaleEntry(key, value, i); 552 return; 553 } 554 } 555 556 tab[i] = new Entry(key, value); 557 int sz = ++size; 558 if (!cleanSomeSlots(i, sz) && sz >= threshold) 559 rehash(); 560 } 561 562 /** 563 * Remove the entry for key. 564 */ 565 private void remove(ThreadLocal key) { 566 Entry[] tab = table; 567 int len = tab.length; 568 int i = key.threadLocalHashCode & (len - 1); 569 for (Entry e = tab[i]; 570 e != null; 571 e = tab[i = nextIndex(i, len)]) { 572 if (e.get() == key) { 573 e.clear(); 574 expungeStaleEntry(i); 575 return; 576 } 577 } 578 } 579 580 /** 581 * Replace a stale entry encountered during a set operation 582 * with an entry for the specified key. The value passed in 583 * the value parameter is stored in the entry, whether or not 584 * an entry already exists for the specified key. 585 *

586 * As a side effect, this method expunges all stale entries in the 587 * "run" containing the stale entry. (A run is a sequence of entries 588 * between two null slots.) 589 * 590 * @param key the key 591 * @param value the value to be associated with key 592 * @param staleSlot index of the first stale entry encountered while 593 * searching for key. 594 */ 595 private void replaceStaleEntry(ThreadLocal key, Object value, 596 int staleSlot) { 597 Entry[] tab = table; 598 int len = tab.length; 599 Entry e; 600 601 // Back up to check for prior stale entry in current run. 602 // We clean out whole runs at a time to avoid continual 603 // incremental rehashing due to garbage collector freeing 604 // up refs in bunches (i.e., whenever the collector runs). 605 int slotToExpunge = staleSlot; 606 for (int i = prevIndex(staleSlot, len); 607 (e = tab[i]) != null; 608 i = prevIndex(i, len)) 609 if (e.get() == null) 610 slotToExpunge = i; 611 612 // Find either the key or trailing null slot of run, whichever 613 // occurs first 614 for (int i = nextIndex(staleSlot, len); 615 (e = tab[i]) != null; 616 i = nextIndex(i, len)) { 617 ThreadLocal k = e.get(); 618 619 // If we find key, then we need to swap it 620 // with the stale entry to maintain hash table order. 621 // The newly stale slot, or any other stale slot 622 // encountered above it, can then be sent to expungeStaleEntry 623 // to remove or rehash all of the other entries in run. 624 if (k == key) { 625 e.value = value; 626 627 tab[i] = tab[staleSlot]; 628 tab[staleSlot] = e; 629 630 // Start expunge at preceding stale entry if it exists 631 if (slotToExpunge == staleSlot) 632 slotToExpunge = i; 633 cleanSomeSlots(expungeStaleEntry(slotToExpunge), len); 634 return; 635 } 636 637 // If we didn't find stale entry on backward scan, the 638 // first stale entry seen while scanning for key is the 639 // first still present in the run. 640 if (k == null && slotToExpunge == staleSlot) 641 slotToExpunge = i; 642 } 643 644 // If key not found, put new entry in stale slot 645 tab[staleSlot].value = null; 646 tab[staleSlot] = new Entry(key, value); 647 648 // If there are any other stale entries in run, expunge them 649 if (slotToExpunge != staleSlot) 650 cleanSomeSlots(expungeStaleEntry(slotToExpunge), len); 651 } 652 653 /** 654 * Expunge a stale entry by rehashing any possibly colliding entries 655 * lying between staleSlot and the next null slot. this also expunges 656 * any other stale entries encountered before the trailing null. See 657 * Knuth, Section 6.4 658 * 译: 659 * 通过重新散列位于staleSlot和下一个null插槽之间的任何可能冲突的条目来清除 660 * 陈旧的条目。这还将删除尾随null之前遇到的所有其他过时的条目。 661 * 662 * @param staleSlot index of slot known to have null key 663 * @return the index of the next null slot after staleSlot 664 * (all between staleSlot and this slot will have been checked 665 * for expunging). 666 */ 667 private int expungeStaleEntry(int staleSlot) { 668 Entry[] tab = table; 669 int len = tab.length; 670 671 // expunge entry at staleSlot 672 tab[staleSlot].value = null; 673 tab[staleSlot] = null; 674 size--; 675 676 // Rehash until we encounter null 677 Entry e; 678 int i; 679 for (i = nextIndex(staleSlot, len); 680 (e = tab[i]) != null; 681 i = nextIndex(i, len)) { 682 ThreadLocal k = e.get(); 683 if (k == null) { 684 e.value = null; 685 tab[i] = null; 686 size--; 687 } else { 688 int h = k.threadLocalHashCode & (len - 1); 689 if (h != i) { 690 tab[i] = null; 691 692 // Unlike Knuth 6.4 Algorithm R, we must scan until 693 // null because multiple entries could have been stale. 694 while (tab[h] != null) 695 h = nextIndex(h, len); 696 tab[h] = e; 697 } 698 } 699 } 700 return i; 701 } 702 703 /** 704 * Heuristically scan some cells looking for stale entries. 705 * This is invoked when either a new element is added, or 706 * another stale one has been expunged. It performs a 707 * logarithmic number of scans, as a balance between no 708 * scanning (fast but retains garbage) and a number of scans 709 * proportional to number of elements, that would find all 710 * garbage but would cause some insertions to take O(n) time. 711 * 译: 712 * 启发式扫描某些单元以查找陈旧条目。当添加了新元素或已删除另一旧 713 * 元素时,将调用此方法。它执行对数扫描,作为无扫描(快速但保留垃 714 * 圾)和与元素数量成正比的扫描数量之间的平衡,这会发现所有垃圾, 715 * 但会导致某些插入花费O(n)时间。 716 * 717 * @param i a position known NOT to hold a stale entry. The 718 * scan starts at the element after i. 719 * @param n scan control: {@code log2(n)} cells are scanned, 720 * unless a stale entry is found, in which case 721 * {@code log2(table.length)-1} additional cells are scanned. 722 * When called from insertions, this parameter is the number 723 * of elements, but when from replaceStaleEntry, it is the 724 * table length. (Note: all this could be changed to be either 725 * more or less aggressive by weighting n instead of just 726 * using straight log n. But this version is simple, fast, and 727 * seems to work well.) 728 * @return true if any stale entries have been removed. 729 */ 730 private boolean cleanSomeSlots(int i, int n) { 731 boolean removed = false; 732 Entry[] tab = table; 733 int len = tab.length; 734 do { 735 i = nextIndex(i, len); 736 Entry e = tab[i]; 737 if (e != null && e.get() == null) { 738 n = len; 739 removed = true; 740 i = expungeStaleEntry(i); 741 } 742 } while ((n >>>= 1) != 0); 743 return removed; 744 } 745 746 /** 747 * Re-pack and/or re-size the table. First scan the entire 748 * table removing stale entries. If this doesn't sufficiently 749 * shrink the size of the table, double the table size. 750 * 译: 751 * 重新包装和/或调整表大小。首先扫描整个表,删除陈旧的条目。 752 * 如果这还不足以缩小表格的大小,请将表格大小加倍。 753 */ 754 private void rehash() { 755 expungeStaleEntries(); 756 757 // Use lower threshold for doubling to avoid hysteresis 758 if (size >= threshold - threshold / 4) 759 resize(); 760 } 761 762 /** 763 * Double the capacity of the table. 764 * 使表的容积几倍。 765 */ 766 private void resize() { 767 Entry[] oldTab = table; 768 int oldLen = oldTab.length; 769 int newLen = oldLen * 2; 770 Entry[] newTab = new Entry[newLen]; 771 int count = 0; 772 773 for (int j = 0; j < oldLen; ++j) { 774 Entry e = oldTab[j]; 775 if (e != null) { 776 ThreadLocal k = e.get(); 777 if (k == null) { 778 e.value = null; // Help the GC 779 } else { 780 int h = k.threadLocalHashCode & (newLen - 1); 781 while (newTab[h] != null) 782 h = nextIndex(h, newLen); 783 newTab[h] = e; 784 count++; 785 } 786 } 787 } 788 789 setThreshold(newLen); 790 size = count; 791 table = newTab; 792 } 793 794 /** 795 * Expunge all stale entries in the table. 796 * 清除表中所有过时条目 797 */ 798 private void expungeStaleEntries() { 799 Entry[] tab = table; 800 int len = tab.length; 801 for (int j = 0; j < len; j++) { 802 Entry e = tab[j]; 803 if (e != null && e.get() == null) 804 expungeStaleEntry(j); 805 } 806 } 807 } 808 }

 

 1 /*
 2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 3  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 4  *
 5  *
 6  *
 7  *
 8  *
 9  *
10  *
11  *
12  *
13  *
14  *
15  *
16  *
17  *
18  *
19  *
20  *
21  *
22  *
23  *
24  */
25 package java.util.function;
26 
27 /**
28  * 该类函数式接口应用于支持Lambda表达式的API中,
29  * Supplier接口用于提供一个T类对象。
30  */
31 
32 /**
33  * Represents a supplier of results.
34  * 代表结果的提供者
35  *
36  * 

There is no requirement that a new or distinct result be returned each 37 * time the supplier is invoked. 38 * 并不要求每次调用都返回一个新的或者不同的结果。 39 * 40 *

This is a functional interface 41 * whose functional method is {@link #get()}. 42 * 43 * @param the type of results supplied by this supplier 44 * @since 1.8 45 */ 46 @FunctionalInterface 47 public interface Supplier { 48 49 /** 50 * Gets a result. 51 * 52 * @return a result 53 */ 54 T get(); 55 }

你可能感兴趣的:(ThreadLocal源码阅读)