lianqu1989 2015-06-13 11:19 采纳率: 0%
浏览 2735
已采纳

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

先上代码吧。

package thread;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/**
 * 这样的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条回答 默认 最新

  • danielinbiti 2015-06-13 15:08
    关注
     几点错误
     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。每个线程单独对象就不存在被覆盖的情况。
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 3月3日

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 MATLAB动图问题
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名