问题描述
直接贴代码了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 用来维护对象TestIprivate 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;@Overridepublic 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天了。。。
解决方案
你没有理解ThreadLocal的含义....ThreadLocal是针对本线程进行设置和读取, 你下面这个是在main所在线程里设置的... TestI testI = new TestI(); //创建一个ThreadLocal来维护这个对象 LocalObject localObject = new LocalObject(); localObject.addTestI(testI); 当然只能从main所在的线程里读取了.你启动的TestThread线程里, 根本就没有设置过, 怎么可能读取到呢?
解决方案二:
threadlocal里面存的东西,就是自己线程的一个副本。用以隔离线程之间的相互影响,这么传是传不进去的。
解决方案三:
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; } }ThreadLocal<T> 必須在線程裡set他的get才會抓得到,先set在丟進線程是get不到值的。
解决方案四:
没仔细看你的代码,只是提醒一下ThreadLocal 其实只是创建一个id,真正你往ThreadLocal里面set object,这个object其实是存在当前线程的某个map里面,你get的时候也是根据这个id从当前线程里面拿东西。不同的线程是不能共享你放到threadlocal里面的同一对象的,即你一个线程put,另外一个线程get是拿不到东西的。