开发者社区> 问答> 正文

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

/**
 * 这样的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也是一样的效果。
但是实在不知道哪里出了问题,求大神指教。

展开
收起
蛮大人123 2016-03-13 14:17:12 2390 0
1 条回答
写回答
取消 提交回答
  • 我说我不帅他们就打我,还说我虚伪

    几点错误
    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。每个线程单独对象就不存在被覆盖的情况。

    2019-07-17 19:02:32
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
建立联系方法之一 立即下载
低代码开发师(初级)实战教程 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载

相关实验场景

更多