java threadlocal的作用_java多线程18: ThreadLocal的作用

从上一篇对于ThreadLocal的分析来看,可以得出结论:ThreadLocal不是用来解决共享对象的多线程访问问题的,通过ThreadLocal的set()方法设置到线程的ThreadLocal.ThreadLocalMap里的是是线程自己要存储的对象,其他线程不需要去访问,也是访问不到的。各个线程中的ThreadLocal.ThreadLocalMap以及ThreadLocal.ThreadLocal中的值都是不同的对象。

至于为什么要使用ThreadLocal,不妨这么考虑这个问题。Java Web中,写一个Servlet:

public class Servlet extendsHttpServlet

{protected voiddoGet(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException

{this.doGet(request, response);

}protected voiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException

{

}

}

我在一个普通JavaBean内想拿到这个HttpServletRequest,但是无法通过参数传递的方式:

public classOperateRequest

{publicString operateRequest()

{return null;

}

}

这时候怎么办?第一个解决方案,Servlet类中定义一个全局的HttpServletRequest,至于怎么定义就随便了,可以定义成静态的,也可以定义成非静态的但是对外提供setter/getter,然后operateRequest()方法每次都取这个全局的HttpServletRequest就可以了。

不否认,这是一种可行的解决方案,但是这种解决方案有一个很大的缺点:竞争。既然HttpServletRequest是全局的,那势必要引入同步机制来保证线程安全性,引入同步机制意味着牺牲响应给用户的时间----这在注重与用户之间响应的Java Web中是难以容忍的。

所以,我们引入ThreadLocal,既然ThreadLocal.ThreadLocalMap是线程独有的,别的线程访问不了也没必要访问,那我们通过ThreadLocal把HttpServletRequest设置到线程的ThreadLocal.ThreadLocalMap里面去不就好了?这样,在一次请求中哪里需要用到HttpServletRequest,就使用ThreadLocal的get()方法就把这个HttpServletRequest给取出来了,是不是一个很好的解决方案呢?

在这里我原先也写了篇笔记 ,可以先看看java 中的 ThreadLocal

ThreadLocal使用

忘记上面那个复杂的问题,我们来看一下ThreadLocal的简单使用,首先ThreadLocal肯定是全局共享的:

public classTools

{public static ThreadLocal t1 = new ThreadLocal();

}

写一个线程往ThreadLocal里面塞值:

public class ThreadLocalThread extendsThread

{private static AtomicInteger ai = newAtomicInteger();publicThreadLocalThread(String name)

{super(name);

}public voidrun()

{try{for (int i = 0; i < 3; i++)

{

Tools.t1.set(ai.addAndGet(1) + "");

System.out.println(this.getName() + " get value--->" +Tools.t1.get());

Thread.sleep(200);

}

}catch(InterruptedException e)

{

e.printStackTrace();

}

}

}

写个main函数,启动三个ThreadLocalThread:

public static void main(String[] args) throwsException

{

ThreadLocalThread a= new ThreadLocalThread("ThreadA");

ThreadLocalThread b= new ThreadLocalThread("ThreadB");

ThreadLocalThread c= new ThreadLocalThread("ThreadC");

a.start();

b.start();

c.start();

}

看一下运行结果:

ThreadA get value--->1ThreadC get value--->2ThreadB get value--->3ThreadB get value--->4ThreadC get value--->6ThreadA get value--->5ThreadC get value--->8ThreadA get value--->7ThreadB get value--->9

看到每个线程的里都有自己的String,并且互不影响----因为绝对不可能出现数字重复的情况。用一个ThreadLocal也可以多次set一个数据,set仅仅表示的是线程的ThreadLocal.ThreadLocalMap中table的某一位置的value被覆盖成你最新设置的那个数据而已,对于同一个ThreadLocal对象而言,set后,table中绝不会多出一个数据,这里要注意,如果第一次没有给ThreadLocal设置值的话,是会返回null的。

ThreadLocal.get 返回null解决

6fe55270846348c0c3e77a71c99dc0b5.png

f91983b78a46fe9b6ae602629c152097.png

上面的对threadlocal 进行了初始化,从而没有进入 判断为null的if分支

InheritableThreadLocal的使用,值继承,继承父线程InheritableThreadLocal的值

d86f91b095bdf6f1f5274c0ed6fc9334.png

1cef59c0a3f73ab8e005b60d852e5188.png

a066c23290a7b518a63538314042ca91.png

aff69751606da7f414e0fbcd7b133d4c.png

ca073cbc910ccb83b0bd862ed481d165.png

从上面可以看得出来,使用InheritableThreadLocal子线程会自动继承父线程的InheritableThreadLocal值

InheritableThreadLocal值继承再修改

5b88f33ae7e8f42f08c098a935d2728c.png

51695a025dced752b833b8fc22460429.png

3d512499491fe66eddff8a153631558d.png

跟上面一样,继承childValue可以在子线程使用InheritableThreadLocal自动调用这个方法初始化子线程的值,记住只是初始化,也就是只执行一次,当父线程再次修改InheritableThreadLocal的值时,子线程取的就是父线程修改后的值了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值