ThreadLocal

  ThreadLocalMap的定义是在ThreadLocal类中,真正的引用却是在Thread类中。

  ThreadLocalMap中用于存储数据的entry

static class Entry extends WeakReference<ThreadLocal> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

  这个MapkeyThreadLocal变量,value为用户的值,并不是网上大多数的列子key是线程的名字或者标识。

  1.Thread类中有一个成员变量叫做ThreadLocalMap,它是一个Map,他的KeyThreadLocal

  2.每个线程拥有自己的申明为ThreadLocal类型的变量,所以这个类的名字叫'ThreadLocal':线程自己的(变量)

  3.此变量生命周期是由该线程决定的,开始于第一次初始(get或者set方法)

  4.ThreadLocal的工作原理决定了:每个线程独自拥有一个变量,并非共享或者拷贝

 

  关于内存泄漏:

  虽然ThreadLocalMap已经使用了weakReference,但是还是建议能够显示的使用remove方法。

import java.util.HashMap;
import java.util.Random;

public class ThreadLocalTest{
    
    private static ThreadLocal<HashMap<String,Integer>> tl = new ThreadLocal<HashMap<String,Integer>>(){
        protected HashMap<String,Integer> initialValue() { 
            return new HashMap<String,Integer>(); 
        }; 
    };
    public static void main(String[] args) {
        Session session1 = new Session(tl);
        Session session2 = new Session(tl);
        Session session3 = new Session(tl);
        Thread t1 = new Thread(session1,"session1");
        Thread t2 = new Thread(session2,"session2");
        Thread t3 = new Thread(session3,"session3");    
        t1.start();
        t2.start();
        t3.start();
        try{
            t1.join();
            t2.join();
            t3.join();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

class Session implements Runnable{
    ThreadLocal<HashMap<String,Integer>> tl = null;
    Session(ThreadLocal<HashMap<String,Integer>> tl){
        this.tl = tl;
    }
    
    public void setData(Integer data){
        tl.get().put(Thread.currentThread().getName() + "_" + data, data);
    }
    
    public HashMap<String,Integer> getData(){
        return tl.get();
    }

    @Override
    public void run() {
        Random r = new Random();        
        int rand = r.nextInt(10);
        setData(rand);
        
        System.out.println(getData());
    }
}

  setget,或者必须在initialValue中初始化。在哪个线程中set就在那个线程中get。如果存在线程重复使用的情况,就需要remove

  一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程。

  这样用户就可以根据需要,将一些非线程安全的变量以ThreadLocal存放,在同一次请求响应的调用线程中,所有对象所访问的同一ThreadLocal变量都是当前线程所绑定的。

  可以将三个层次中公用的参数放在在线程的ThreadLocal中,而不用以传参数的方式来完成数据的公用。

 

  一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程

  ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。

 

posted on 2015-07-31 23:55  lnlvinso  阅读(288)  评论(0编辑  收藏  举报