关于ThreadLocal的一个测试 大神 帮我看下 为什么run方法里面找不到对象 (为了方便 我把他们都写到一个类中)

直接贴代码了

package test;

public class TestThreadLocal {


    public static void main(String[] args) {

    /*ExecutorService exce = Executors.newCachedThreadPool();

      for(int i=0;i<10;i++){
          
          exce.execute(new Thread(new TestThread(),"this is thread:"+i));
      }
        exce.shutdown();
    }
    */
        //一个公共的对象
        
        TestI testI = new TestI();
        //创建一个ThreadLocal来维护这个对象
        LocalObject localObject = new LocalObject();

        localObject.addTestI(testI);

        //      System.out.println(localObject.getTestI().getI());

        for(int i=0;i<10 ;i++){

            new Thread(new TestThread(localObject),"this is thread:"+i).start(); 

        }

    }
}

class LocalObject{

    //创建一个ThreadLocal 用来维护对象TestI
    private   ThreadLocal<TestI> testIocal = new ThreadLocal<TestI>();


    public  void addTestI(TestI testI){

        testIocal.set(testI);

    }
    public  TestI getTestI(){

        return testIocal.get();
        
    }

    public  void doSomeThing(){

        getTestI().setI();
    }
}


class TestThread implements Runnable{

    private  LocalObject localObject ;

    public TestThread(LocalObject localObject){

        this.localObject = localObject;
        
    }
    private int i=10;
    
    @Override
    public void run() {

        
        while(this.localObject.getTestI().getI()>0){
            
            this.localObject.doSomeThing();
            
            i--;
            
            if(this.localObject.getTestI().getI()!=i){

                System.out.println(Thread.currentThread().getName()+"not matched");
            }
            //  System.out.println(Thread.currentThread().getName()+"::"+LocalObject.getTestI().getI());
        }
    }

}

class TestI  {

    
    private int i=10;
    
    public void setI(){
        
        i--;        
    }
    public int   getI(){
        
        return i;
    }
    
    
}

 报错是Exception in thread "this is thread:1" java.lang.NullPointerException
    at test.TestThread.run(TestThreadLocal.java:75)

 

就是run方法里面找不到对象,但是我通过构造方法注入了一个对象了呀。怎么回事 搞了2天了。。。

4个回答

你没有理解ThreadLocal的含义....

ThreadLocal是针对本线程进行设置和读取, 你下面这个是在main所在线程里设置的...

     TestI testI = new TestI();  
    //创建一个ThreadLocal来维护这个对象  
    LocalObject localObject = new LocalObject();  

    localObject.addTestI(testI);  

当然只能从main所在的线程里读取了.

你启动的TestThread线程里, 根本就没有设置过, 怎么可能读取到呢?

zhanghaj011
zhanghaj011 一语点醒梦中人呀。。。现在彻底明白了。。 大神 谢谢啦
大约 6 年之前 回复

没仔细看你的代码,只是提醒一下ThreadLocal 其实只是创建一个id,真正你往ThreadLocal里面set object,这个object其实是存在当前线程的某个map里面,你get的时候也是根据这个id从当前线程里面拿东西。不同的线程是不能共享你放到threadlocal里面的同一对象的,即你一个线程put,另外一个线程get是拿不到东西的。

[code="java"]
public class Test2 {

public static void main(String[] args) {  

/*ExecutorService exce = Executors.newCachedThreadPool(); 

  for(int i=0;i<10;i++){ 

      exce.execute(new Thread(new TestThread(),"this is thread:"+i)); 
  } 
    exce.shutdown(); 
} 
*/  
    //一个公共的对象  



    for(int i=0;i<10 ;i++){  

        new Thread(new TestThread(),"this is thread:"+i).start();   

    }  

}  

}

class LocalObject{

//创建一个ThreadLocal 用来维护对象TestI  
public   ThreadLocal<TestI> testIocal = new ThreadLocal<TestI>();  


public  void addTestI(TestI testI){  

    testIocal.set(testI);  

}  
public  TestI getTestI(){  

    return testIocal.get();  

}  

public  void doSomeThing(){  

    getTestI().setI();  
}  

}

class TestThread implements Runnable{

private int i=10;  

@Override  
public void run() {  
     TestI testI = new TestI();  
     //创建一个ThreadLocal来维护这个对象  
     LocalObject localObject = new LocalObject();  

     localObject.addTestI(testI);  

    while(localObject.getTestI().getI()>0){  

        localObject.doSomeThing();  

        i--;  
        if(localObject.getTestI().getI()!=i){  

            System.out.println(Thread.currentThread().getName()+"not matched");  
        }  
        //  System.out.println(Thread.currentThread().getName()+"::"+LocalObject.getTestI().getI());  
    }  
}  

}

class TestI {

public int i=10;  

public void setI(){  

    this.i--;          
}  
public int   getI(){  

    return this.i;  
}  

}
[/code]

ThreadLocal 必須在線程裡set他的get才會抓得到,先set在丟進線程是get不到值的。

threadlocal里面存的东西,就是自己线程的一个副本。用以隔离线程之间的相互影响,这么传是传不进去的。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问