您的位置:首页 > 其它

ThreadLocal是否会引起内存溢出?

2013-02-11 19:50 295 查看
最近碰到一个使用ThreadLocal时因为未调用remove()而险些引起内存溢出的问题,所以看了下ThreadLocal的源码,结合线程池原理做一个简单的分析,确认是否最终会导致内存溢出。

既然是因为没调用remove()方法而险些导致内存溢出,那首先看下remove()方法中做了什么。

Java代码


 




public void remove() {   
        ThreadLocalMap m = getMap(Thread.currentThread());   
        if (m != null)   
            m.remove(this);   
    }  

public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}


从remove()的实现来看就是一个map.remove()的调用。既然不调用map.remove()可能会引起内存溢出的话,就需要看看ThreadLocalMap的实现了。

Java代码


 




 /**  
  * ThreadLocalMap is a customized hash map suitable only for
 
  * maintaining thread local values. No operations are exported
 
  * outside of the ThreadLocal class. The class is package private to
 
  * allow declaration of fields in class Thread.  To help deal with
 
  * very large and long-lived usages, the hash table entries use
 
  * WeakReferences for keys. However, since reference queues are not
 
  * used, stale entries are guaranteed to be removed only when
 
  * the table starts running out of space.
 
  */  
 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;   
         }   
     }   
  
     /**  
      * The initial capacity -- MUST be a power of two.
 
      */  
     private static final int INITIAL_CAPACITY = 16;
  
  
     /**  
      * The table, resized as necessary.  
      * table.length MUST always be a power of two.
 
      */  
     private Entry[] table;   
  
     /**  
      * The number of entries in the table.
 
      */  
     private int size = 0;   
  
     /**  
      * The next size value at which to resize.
 
      */  
     private int threshold; // Default to 0
  
  
     /**  
      * Set the resize threshold to maintain at worst a 2/3 load factor.
 
      */  
     private void setThreshold(int len) {   
         threshold = len * 2 / 3;   
     }   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: