关于一个全局map实现ThreadLocal遇到的错误-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

关于一个全局map实现ThreadLocal遇到的错误

2016-03-13 14:17:12 1864 1
/**
 * 这样的map属于全局级别的,会冲突,而且这样的实现方法好像是1.3以前的方法
 * @author Han
 */
public class MyThreadLocalDemo {
    private static Map<Thread,String> map = new HashMap<Thread,String>();
    private static String contextStr = "";


    public static void set(String str){
        //System.out.println(map.containsKey(Thread.currentThread()));
        map.put(Thread.currentThread(), str);
    }

    public static String get(){
        System.out.println(map.keySet());
        return map.get(Thread.currentThread());
    }

    public static String getStr(){
        return contextStr;
    }
    public static void setStr(String str){
        contextStr = str;
    }

    public static void print(){
        System.out.println(map);
    }

    public class MyThread extends Thread{
//      public MyThread(String name){
//          super(name);
//      }
        @Override
        public void run() {
            int i = new Random().nextInt(10);
            String str = Thread.currentThread().getId()+","+i;
            MyThreadLocalDemo.set(str);
            MyThreadLocalDemo.setStr(str);
            System.out.println("```threadlocal的值"+str);
            System.out.println("```string的值"+str);
            //System.out.println(Thread.currentThread());
            try {
                Thread.currentThread().sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("`threadlocal的值"+MyThreadLocalDemo.get());
            System.out.println("`String的值"+MyThreadLocalDemo.getStr());
            //print();
        }
    }

    public static void main(String[] args) {
        //运行以下代码可以看出,两个线程,持有的threadlocal没有因为另一个改变了值而发生改变
//      for(int i = 0;i<20;i++){
//          Thread t1 = new MyThreadLocalDemo().new MyThread();
//          Thread t2 = new MyThreadLocalDemo().new MyThread();
//          t1.start();
//          t2.start();
//      }
        Thread t1 = new MyThreadLocalDemo().new MyThread();
        Thread t2 = new MyThreadLocalDemo().new MyThread();
        t1.start();
        t2.start();
    }
}

这个程序的执行结果,有时候会get 出来 null,有时候不会。没想明白。ThreadLocal是为每个Thread对象都会一个独自的ThreadMap,不考虑性能的话,我觉得用map也是一样的效果。
但是实在不知道哪里出了问题,求大神指教。

取消 提交回答
全部回答(1)
  • 蛮大人123
    2019-07-17 19:02:32

    几点错误
    1、MyThreadLocalDemo.setStr(str); 这个无意义,因为contextStr 是静态变量,肯定是最后一个更新的值,不是每个线程的值
    2、出现null的原因是 map.put(Thread.currentThread(), str);这句话,因为多个线程,hashmap不是现场安全的,可能两个线程同时添加到同一个节点上,有一个线程的节点被覆盖了。值也就不存在了。
    解决方式

     public static void set(String str){
            //System.out.println(map.containsKey(Thread.currentThread()));
            map.put(Thread.currentThread(), str);
        }
            改成
            public static synchronized void set(String str){
            //System.out.println(map.containsKey(Thread.currentThread()));
            map.put(Thread.currentThread(), str);
        }

    或者你也为每个thread增加map。每个线程单独对象就不存在被覆盖的情况。

    0 0
+关注
蛮大人123
我说我不帅他们就打我,还说我虚伪
0
文章
7733
问答
问答排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载